OSDN Git Service

Initial revision
authorgrimmd <none@none>
Thu, 1 Mar 2001 21:01:27 +0000 (21:01 +0000)
committergrimmd <none@none>
Thu, 1 Mar 2001 21:01:27 +0000 (21:01 +0000)
69 files changed:
Src/editlib/asp.cpp [new file with mode: 0644]
Src/editlib/basic.cpp [new file with mode: 0644]
Src/editlib/batch.cpp [new file with mode: 0644]
Src/editlib/ccrystaleditview.cpp [new file with mode: 0644]
Src/editlib/ccrystaleditview.h [new file with mode: 0644]
Src/editlib/ccrystaleditview.inl [new file with mode: 0644]
Src/editlib/ccrystaltextbuffer.cpp [new file with mode: 0644]
Src/editlib/ccrystaltextbuffer.h [new file with mode: 0644]
Src/editlib/ccrystaltextbuffer.inl [new file with mode: 0644]
Src/editlib/ccrystaltextview.cpp [new file with mode: 0644]
Src/editlib/ccrystaltextview.h [new file with mode: 0644]
Src/editlib/ccrystaltextview.inl [new file with mode: 0644]
Src/editlib/ccrystaltextview2.cpp [new file with mode: 0644]
Src/editlib/ceditreplacedlg.cpp [new file with mode: 0644]
Src/editlib/ceditreplacedlg.h [new file with mode: 0644]
Src/editlib/cfindtextdlg.cpp [new file with mode: 0644]
Src/editlib/cfindtextdlg.h [new file with mode: 0644]
Src/editlib/chcondlg.cpp [new file with mode: 0644]
Src/editlib/chcondlg.h [new file with mode: 0644]
Src/editlib/cplusplus.cpp [new file with mode: 0644]
Src/editlib/cregexp.cpp [new file with mode: 0644]
Src/editlib/cregexp.h [new file with mode: 0644]
Src/editlib/crystaleditviewex.cpp [new file with mode: 0644]
Src/editlib/crystaleditviewex.h [new file with mode: 0644]
Src/editlib/crystalparser.cpp [new file with mode: 0644]
Src/editlib/crystalparser.h [new file with mode: 0644]
Src/editlib/crystaltextblock.cpp [new file with mode: 0644]
Src/editlib/crystaltextblock.h [new file with mode: 0644]
Src/editlib/cs2cs.cpp [new file with mode: 0644]
Src/editlib/cs2cs.h [new file with mode: 0644]
Src/editlib/dcl.cpp [new file with mode: 0644]
Src/editlib/editcmd.h [new file with mode: 0644]
Src/editlib/editreg.h [new file with mode: 0644]
Src/editlib/edtlib.cpp [new file with mode: 0644]
Src/editlib/edtlib.h [new file with mode: 0644]
Src/editlib/filesup.cpp [new file with mode: 0644]
Src/editlib/filesup.h [new file with mode: 0644]
Src/editlib/filesup.inl [new file with mode: 0644]
Src/editlib/fortran.cpp [new file with mode: 0644]
Src/editlib/fpattern.cpp [new file with mode: 0644]
Src/editlib/fpattern.h [new file with mode: 0644]
Src/editlib/gotodlg.cpp [new file with mode: 0644]
Src/editlib/gotodlg.h [new file with mode: 0644]
Src/editlib/html.cpp [new file with mode: 0644]
Src/editlib/is.cpp [new file with mode: 0644]
Src/editlib/java.cpp [new file with mode: 0644]
Src/editlib/lisp.cpp [new file with mode: 0644]
Src/editlib/memcombo.cpp [new file with mode: 0644]
Src/editlib/memcombo.h [new file with mode: 0644]
Src/editlib/memcombo.inl [new file with mode: 0644]
Src/editlib/pascal.cpp [new file with mode: 0644]
Src/editlib/perl.cpp [new file with mode: 0644]
Src/editlib/php.cpp [new file with mode: 0644]
Src/editlib/python.cpp [new file with mode: 0644]
Src/editlib/registry.cpp [new file with mode: 0644]
Src/editlib/registry.h [new file with mode: 0644]
Src/editlib/rexx.cpp [new file with mode: 0644]
Src/editlib/rsrc.cpp [new file with mode: 0644]
Src/editlib/sgml.cpp [new file with mode: 0644]
Src/editlib/sh.cpp [new file with mode: 0644]
Src/editlib/siod.cpp [new file with mode: 0644]
Src/editlib/splash.cpp [new file with mode: 0644]
Src/editlib/splash.h [new file with mode: 0644]
Src/editlib/sql.cpp [new file with mode: 0644]
Src/editlib/statbar.cpp [new file with mode: 0644]
Src/editlib/statbar.h [new file with mode: 0644]
Src/editlib/tcl.cpp [new file with mode: 0644]
Src/editlib/tex.cpp [new file with mode: 0644]
Src/editlib/wispelld.h [new file with mode: 0644]

diff --git a/Src/editlib/asp.cpp b/Src/editlib/asp.cpp
new file mode 100644 (file)
index 0000000..698513a
--- /dev/null
@@ -0,0 +1,951 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    asp.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  HTML syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszHtmlKeywordList[] =
+  {
+    // HTML section
+    _T ("DOCTYPE"),
+    _T ("PUBLIC"),
+    _T ("FRAME"),
+    _T ("FRAMESET"),
+    _T ("NOFRAMES"),
+    // HEAD section
+    _T ("HEAD"),
+    _T ("TITLE"),
+    _T ("ISINDEX"),
+    _T ("META"),
+    _T ("LINK"),
+    _T ("BASE"),
+    _T ("SCRIPT"),
+    _T ("STYLE"),
+    // BODY section
+    _T ("BODY"),
+    // headings
+    _T ("H1"),
+    _T ("H2"),
+    _T ("H3"),
+    _T ("H4"),
+    _T ("H5"),
+    _T ("H6"),
+    // lists
+    _T ("UL"),
+    _T ("OL"),
+    _T ("DIR"),
+    _T ("MENU"),
+    _T ("LI"),
+    _T ("DL"),
+    _T ("DT"),
+    _T ("DD"),
+    // text containers
+    _T ("P"),
+    _T ("PRE"),
+    _T ("BLOCKQUOTE"),
+    _T ("ADDRESS"),
+    // others
+    _T ("DIV"),
+    _T ("SPAN"),
+    _T ("CENTER"),
+    _T ("HR"),
+    _T ("FORM"),
+    _T ("TABLE"),
+    _T ("LEFT"),
+    _T ("RIGHT"),
+    _T ("TOP"),
+    // logical markup
+    _T ("EM"),
+    _T ("STRONG"),
+    _T ("DFN"),
+    _T ("CODE"),
+    _T ("SAMP"),
+    _T ("KBD"),
+    _T ("VAR"),
+    _T ("CITE"),
+    // physical markup
+    _T ("TT"),
+    _T ("I"),
+    _T ("B"),
+    _T ("U"),
+    _T ("STRIKE"),
+    _T ("BIG"),
+    _T ("SMALL"),
+    _T ("SUB"),
+    _T ("SUP"),
+    // special markup
+    _T ("A"),
+    _T ("BASEFONT"),
+    _T ("IMG"),
+    _T ("APPLET"),
+    _T ("PARAM"),
+    _T ("FONT"),
+    _T ("BR"),
+    _T ("MAP"),
+    _T ("AREA"),
+    // forms
+    _T ("INPUT"),
+    _T ("SELECT"),
+    _T ("OPTION"),
+    _T ("TEXTAREA"),
+    _T ("ONCLICK"),
+    // tables
+    _T ("CAPTION"),
+    _T ("TR"),
+    _T ("TH"),
+    _T ("TD"),
+    _T ("HTML"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("ACTION"),
+    _T ("ALIGN"),
+    _T ("ALINK"),
+    _T ("BACKGROUND"),
+    _T ("BGCOLOR"),
+    _T ("COLOR"),
+    _T ("COMPACT"),
+    _T ("CONTENT"),
+    _T ("ENCTYPE"),
+    _T ("FACE"),
+    _T ("HEIGHT"),
+    _T ("HREF"),
+    _T ("HTTP-EQUIV"),
+    _T ("LINK"),
+    _T ("METHOD"),
+    _T ("NAME"),
+    _T ("PROMPT"),
+    _T ("REL"),
+    _T ("REV"),
+    _T ("START"),
+    _T ("TEXT"),
+    _T ("TYPE"),
+    _T ("VALUE"),
+    _T ("VLINK"),
+    _T ("WIDTH"),
+    _T ("ADD_DATE"),
+    _T ("ALT"),
+    _T ("BORDER"),
+    _T ("CELLPADDING"),
+    _T ("CELLSPACING"),
+    _T ("CHECKED"),
+    _T ("CLEAR"),
+    _T ("CODE"),
+    _T ("CODEBASE"),
+    _T ("COLS"),
+    _T ("COLSPAN"),
+    _T ("COORDS"),
+    _T ("FOLDED"),
+    _T ("HSPACE"),
+    _T ("ISMAP"),
+    _T ("LAST_MODIFIED"),
+    _T ("LAST_VISIT"),
+    _T ("MAXLENGTH"),
+    _T ("MULTIPLE"),
+    _T ("NORESIZE"),
+    _T ("NOSHADE"),
+    _T ("NOWRAP"),
+    _T ("ROWS"),
+    _T ("ROWSPAN"),
+    _T ("SELECTED"),
+    _T ("SHAPE"),
+    _T ("SIZE"),
+    _T ("SRC"),
+    _T ("TARGET"),
+    _T ("USEMAP"),
+    _T ("VALIGN"),
+    _T ("VSPACE"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T ("nbsp"),
+    _T ("quot"),
+    _T ("amp"),
+    _T ("lt"),
+    _T ("lt"),
+    _T ("gt"),
+    _T ("copy"),
+    _T ("reg"),
+    _T ("acute"),
+    _T ("laquo"),
+    _T ("raquo"),
+    _T ("iexcl"),
+    _T ("iquest"),
+    _T ("Agrave"),
+    _T ("agrave"),
+    _T ("Aacute"),
+    _T ("aacute"),
+    _T ("Acirc"),
+    _T ("acirc"),
+    _T ("Atilde"),
+    _T ("atilde"),
+    _T ("Auml"),
+    _T ("auml"),
+    _T ("Aring"),
+    _T ("aring"),
+    _T ("AElig"),
+    _T ("aelig"),
+    _T ("Ccedil"),
+    _T ("ccedil"),
+    _T ("ETH"),
+    _T ("eth"),
+    _T ("Egrave"),
+    _T ("egrave"),
+    _T ("Eacute"),
+    _T ("eacute"),
+    _T ("Ecirc"),
+    _T ("ecirc"),
+    _T ("Euml"),
+    _T ("euml"),
+    _T ("Igrave"),
+    _T ("igrave"),
+    _T ("Iacute"),
+    _T ("iacute"),
+    _T ("Icirc"),
+    _T ("icirc"),
+    _T ("Iuml"),
+    _T ("iuml"),
+    _T ("Ntilde"),
+    _T ("ntilde"),
+    _T ("Ograve"),
+    _T ("ograve"),
+    _T ("Oacute"),
+    _T ("oacute"),
+    _T ("Ocirc"),
+    _T ("ocirc"),
+    _T ("Otilde"),
+    _T ("otilde"),
+    _T ("Ouml"),
+    _T ("ouml"),
+    _T ("Oslash"),
+    _T ("oslash"),
+    _T ("Ugrave"),
+    _T ("ugrave"),
+    _T ("Uacute"),
+    _T ("uacute"),
+    _T ("Ucirc"),
+    _T ("ucirc"),
+    _T ("Uuml"),
+    _T ("uuml"),
+    _T ("Yacute"),
+    _T ("yacute"),
+    _T ("yuml"),
+    _T ("THORN"),
+    _T ("thorn"),
+    _T ("szlig"),
+    _T ("sect"),
+    _T ("para"),
+    _T ("micro"),
+    _T ("brvbar"),
+    _T ("plusmn"),
+    _T ("middot"),
+    _T ("uml"),
+    _T ("cedil"),
+    _T ("ordf"),
+    _T ("ordm"),
+    _T ("not"),
+    _T ("shy"),
+    _T ("macr"),
+    _T ("deg"),
+    _T ("sup1"),
+    _T ("sup2"),
+    _T ("sup3"),
+    _T ("frac14"),
+    _T ("frac12"),
+    _T ("frac34"),
+    _T ("times"),
+    _T ("divide"),
+    _T ("cent"),
+    _T ("pound"),
+    _T ("curren"),
+    _T ("yen"),
+    NULL
+  };
+
+static LPTSTR s_apszAspKeywordList[] =
+  {
+    _T ("If"),
+    _T ("Function"),
+    _T ("Else"),
+    _T ("End"),
+    _T ("For"),
+    _T ("Next"),
+    _T ("While"),
+    _T ("Wend"),
+    _T ("SMDoMenu"),
+    _T ("GetAttrType"),
+    _T ("GetAttrName"),
+    _T ("GetAttrValString"),
+    _T ("GetAttrValFloat"),
+    _T ("GetAttrValInt"),
+    _T ("GetAttrValBool"),
+    _T ("GetAttrValEnumInt"),
+    _T ("GetAttrValEnumString"),
+    _T ("GetClassId"),
+    _T ("GetGeoType"),
+    _T ("SetAttrValString"),
+    _T ("SetAttrValInt"),
+    _T ("SetAttrValFloat"),
+    _T ("SetAttrValBool"),
+    _T ("SetAttrValEnumString"),
+    _T ("SetAttrValEnumInt"),
+    _T ("CreateVerifyItem"),
+    _T ("VerifyCardinalities"),
+    _T ("As"),
+    _T ("Abs"),
+    _T ("AppActivate"),
+    _T ("Asc"),
+    _T ("Atn"),
+    _T ("Beep"),
+    _T ("Call"),
+    _T ("CDbl"),
+    _T ("ChDir"),
+    _T ("ChDrive"),
+    _T ("CheckBox"),
+    _T ("Chr"),
+    _T ("CInt"),
+    _T ("CLng"),
+    _T ("Close"),
+    _T ("Const"),
+    _T ("Cos"),
+    _T ("CreateObject"),
+    _T ("CSng"),
+    _T ("CStr"),
+    _T ("CVar"),
+    _T ("CurDir"),
+    _T ("Date"),
+    _T ("Declare"),
+    _T ("Dialog"),
+    _T ("Dim"),
+    _T ("Dir"),
+    _T ("DlgEnable"),
+    _T ("DlgText"),
+    _T ("DlgVisible"),
+    _T ("Do"),
+    _T ("Double"),
+    _T ("Loop"),
+    _T ("End"),
+    _T ("EOF"),
+    _T ("Erase"),
+    _T ("Exit"),
+    _T ("Exp"),
+    _T ("FileCopy"),
+    _T ("FileLen"),
+    _T ("Fix"),
+    _T ("For"),
+    _T ("To"),
+    _T ("Step"),
+    _T ("Next"),
+    _T ("Format"),
+    _T ("Function"),
+    _T ("GetObject"),
+    _T ("Global"),
+    _T ("GoSub"),
+    _T ("Return"),
+    _T ("GoTo"),
+    _T ("Hex"),
+    _T ("Hour"),
+    _T ("If"),
+    _T ("Then"),
+    _T ("Else"),
+    _T ("Input"),
+    _T ("InputBox"),
+    _T ("InStr"),
+    _T ("Int"),
+    _T ("IsDate"),
+    _T ("IsEmpty"),
+    _T ("IsNull"),
+    _T ("IsNumeric"),
+    _T ("Kill"),
+    _T ("LBound"),
+    _T ("LCase"),
+    _T ("LCase$"),
+    _T ("Left"),
+    _T ("Left$"),
+    _T ("Len"),
+    _T ("Let"),
+    _T ("Line"),
+    _T ("Input#"),
+    _T ("Log"),
+    _T ("Long"),
+    _T ("Mid"),
+    _T ("Minute"),
+    _T ("MkDir"),
+    _T ("Month"),
+    _T ("MsgBox"),
+    _T ("Name"),
+    _T ("Now"),
+    _T ("Oct"),
+    _T ("On"),
+    _T ("Error"),
+    _T ("Open"),
+    _T ("Option"),
+    _T ("Base"),
+    _T ("Print"),
+    _T ("Print"),
+    _T ("Rem"),
+    _T ("Right"),
+    _T ("RmDir"),
+    _T ("Rnd"),
+    _T ("Second"),
+    _T ("Seek"),
+    _T ("Seek"),
+    _T ("Select Case"),
+    _T ("SendKeys"),
+    _T ("Set"),
+    _T ("Shell"),
+    _T ("Sin"),
+    _T ("Space"),
+    _T ("Sqr"),
+    _T ("Static"),
+    _T ("Stop"),
+    _T ("Str"),
+    _T ("StrComp"),
+    _T ("String"),
+    _T ("StringFunction"),
+    _T ("Sub"),
+    _T ("Tan"),
+    _T ("Text"),
+    _T ("TextBox"),
+    _T ("Time"),
+    _T ("TimeSerial"),
+    _T ("TimeValue"),
+    _T ("Trim"),
+    _T ("LTrim"),
+    _T ("RTrim"),
+    _T ("Type"),
+    _T ("UBound"),
+    _T ("UCase"),
+    _T ("Val"),
+    _T ("VarType"),
+    _T ("While"),
+    _T ("Wend"),
+    _T ("With"),
+    _T ("Write"),
+    _T ("Year"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsHtmlKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszHtmlKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsAspKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszAspKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsAspNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+#define COOKIE_USER1            0x0020
+#define COOKIE_EXT_USER1        0x0040
+
+DWORD CCrystalTextView::
+ParseLineAsp (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & (COOKIE_EXT_COMMENT|COOKIE_EXT_USER1);
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~(COOKIE_EXT_COMMENT|COOKIE_EXT_USER1)) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else if (dwCookie & COOKIE_EXT_USER1)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment <!--....-->
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          if (!(dwCookie & COOKIE_EXT_USER1))
+            {
+              if (I > 1 && pszChars[I] == '>' && pszChars[I - 1] == '-' && pszChars[I - 2] == '-')
+                {
+                  dwCookie &= ~COOKIE_EXT_COMMENT;
+                  bRedefineBlock = TRUE;
+                }
+            }
+          continue;
+        }
+
+      if ((dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '\'')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Extended comment <?....?>
+      if (dwCookie & COOKIE_EXT_USER1)
+        {
+          if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+            {
+              dwCookie &= ~COOKIE_EXT_USER1;
+              bRedefineBlock = TRUE;
+              continue;
+            }
+        }
+
+      //  Normal text
+      if ((dwCookie & (COOKIE_PREPROCESSOR|COOKIE_EXT_USER1)) && pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+
+      if ((dwCookie & (COOKIE_PREPROCESSOR|COOKIE_EXT_USER1)) && pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (!(dwCookie & COOKIE_EXT_USER1))
+        {
+          if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength - 3 && pszChars[I] == '<' && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')
+            {
+              DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+              I += 3;
+              dwCookie |= COOKIE_EXT_COMMENT;
+              dwCookie &= ~COOKIE_PREPROCESSOR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (dwCookie & COOKIE_PREPROCESSOR)
+                {
+                  if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                    }
+                  else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                    }
+                  else if (IsAspNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              else if (dwCookie & COOKIE_EXT_USER1)
+                {
+                  if (IsAspKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                    }
+                  else if (IsAspNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                    }
+                  else
+                    {
+                      bool bFunction = FALSE;
+
+                      for (int j = I; j < nLength; j++)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == '(')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                      if (bFunction)
+                        {
+                          DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                        }
+                      else
+                        {
+                          goto next;
+                        }
+                    }
+                }
+              else if (dwCookie & COOKIE_USER1)
+                {
+                  if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+next:
+              ;
+            }
+
+          //  User1 start: <?
+          if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_NORMALTEXT);
+              dwCookie |= COOKIE_EXT_USER1;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor start: < or bracket
+          if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-'))
+            {
+              DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  User1 end: ?>
+          if (dwCookie & COOKIE_EXT_USER1)
+            {
+              if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+                {
+                  dwCookie &= ~COOKIE_EXT_USER1;
+                  nIdentBegin = -1;
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  continue;
+                }
+            }
+
+          //  Preprocessor end: > or bracket
+          if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              if (pszChars[I] == '>')
+                {
+                  dwCookie &= ~COOKIE_PREPROCESSOR;
+                  nIdentBegin = -1;
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  continue;
+                }
+            }
+
+          //  Preprocessor start: &
+          if (!(dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '&')
+            {
+              dwCookie |= COOKIE_USER1;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor end: ;
+          if (dwCookie & COOKIE_USER1)
+            {
+              if (pszChars[I] == ';')
+                {
+                  dwCookie &= ~COOKIE_USER1;
+                  nIdentBegin = -1;
+                  continue;
+                }
+            }
+
+        }
+    }
+
+  if (nIdentBegin >= 0 && (dwCookie & COOKIE_PREPROCESSOR))
+    {
+      if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsAspNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+  else if (nIdentBegin >= 0 && (dwCookie & COOKIE_EXT_USER1))
+    {
+      if (IsAspKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsAspNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  //  User1 start: <?
+  if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
+    {
+      DEFINE_BLOCK (I, COLORINDEX_NORMALTEXT);
+      dwCookie |= COOKIE_EXT_USER1;
+      nIdentBegin = -1;
+      goto end;
+    }
+
+  //  Preprocessor start: < or {
+  if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && (pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')))
+    {
+      DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+      dwCookie |= COOKIE_PREPROCESSOR;
+      nIdentBegin = -1;
+      goto end;
+    }
+
+  //  User1 end: ?>
+  if (dwCookie & COOKIE_EXT_USER1)
+    {
+      if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+        {
+          dwCookie &= ~COOKIE_EXT_USER1;
+          nIdentBegin = -1;
+        }
+    }
+
+  //  Preprocessor end: > or }
+  if (dwCookie & COOKIE_PREPROCESSOR)
+    {
+      if (pszChars[I] == '>')
+        {
+          dwCookie &= ~COOKIE_PREPROCESSOR;
+          nIdentBegin = -1;
+        }
+    }
+
+end:
+  dwCookie &= (COOKIE_EXT_COMMENT | COOKIE_STRING | COOKIE_PREPROCESSOR | COOKIE_EXT_USER1);
+  return dwCookie;
+}
diff --git a/Src/editlib/basic.cpp b/Src/editlib/basic.cpp
new file mode 100644 (file)
index 0000000..6b4304f
--- /dev/null
@@ -0,0 +1,444 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    basic.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Visual Basic syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszBasicKeywordList[] =
+  {
+    _T ("If"),
+    _T ("Function"),
+    _T ("Else"),
+    _T ("End"),
+    _T ("For"),
+    _T ("Next"),
+    _T ("While"),
+    _T ("Wend"),
+    _T ("SMDoMenu"),
+    _T ("GetAttrType"),
+    _T ("GetAttrName"),
+    _T ("GetAttrValString"),
+    _T ("GetAttrValFloat"),
+    _T ("GetAttrValInt"),
+    _T ("GetAttrValBool"),
+    _T ("GetAttrValEnumInt"),
+    _T ("GetAttrValEnumString"),
+    _T ("GetClassId"),
+    _T ("GetGeoType"),
+    _T ("SetAttrValString"),
+    _T ("SetAttrValInt"),
+    _T ("SetAttrValFloat"),
+    _T ("SetAttrValBool"),
+    _T ("SetAttrValEnumString"),
+    _T ("SetAttrValEnumInt"),
+    _T ("CreateVerifyItem"),
+    _T ("VerifyCardinalities"),
+    _T ("As"),
+    _T ("Abs"),
+    _T ("AppActivate"),
+    _T ("Asc"),
+    _T ("Atn"),
+    _T ("Beep"),
+    _T ("Call"),
+    _T ("CDbl"),
+    _T ("ChDir"),
+    _T ("ChDrive"),
+    _T ("CheckBox"),
+    _T ("Chr"),
+    _T ("CInt"),
+    _T ("CLng"),
+    _T ("Close"),
+    _T ("Const"),
+    _T ("Cos"),
+    _T ("CreateObject"),
+    _T ("CSng"),
+    _T ("CStr"),
+    _T ("CVar"),
+    _T ("CurDir"),
+    _T ("Date"),
+    _T ("Declare"),
+    _T ("Dialog"),
+    _T ("Dim"),
+    _T ("Dir"),
+    _T ("DlgEnable"),
+    _T ("DlgText"),
+    _T ("DlgVisible"),
+    _T ("Do"),
+    _T ("Double"),
+    _T ("Loop"),
+    _T ("End"),
+    _T ("EOF"),
+    _T ("Erase"),
+    _T ("Exit"),
+    _T ("Exp"),
+    _T ("FileCopy"),
+    _T ("FileLen"),
+    _T ("Fix"),
+    _T ("For"),
+    _T ("To"),
+    _T ("Step"),
+    _T ("Next"),
+    _T ("Format"),
+    _T ("Function"),
+    _T ("GetObject"),
+    _T ("Global"),
+    _T ("GoSub"),
+    _T ("Return"),
+    _T ("GoTo"),
+    _T ("Hex"),
+    _T ("Hour"),
+    _T ("If"),
+    _T ("Then"),
+    _T ("Else"),
+    _T ("Input"),
+    _T ("InputBox"),
+    _T ("InStr"),
+    _T ("Int"),
+    _T ("IsDate"),
+    _T ("IsEmpty"),
+    _T ("IsNull"),
+    _T ("IsNumeric"),
+    _T ("Kill"),
+    _T ("LBound"),
+    _T ("LCase"),
+    _T ("LCase$"),
+    _T ("Left"),
+    _T ("Left$"),
+    _T ("Len"),
+    _T ("Let"),
+    _T ("Line"),
+    _T ("Input#"),
+    _T ("Log"),
+    _T ("Long"),
+    _T ("Mid"),
+    _T ("Minute"),
+    _T ("MkDir"),
+    _T ("Month"),
+    _T ("MsgBox"),
+    _T ("Name"),
+    _T ("Now"),
+    _T ("Oct"),
+    _T ("On"),
+    _T ("Error"),
+    _T ("Open"),
+    _T ("Option"),
+    _T ("Base"),
+    _T ("Print"),
+    _T ("Print"),
+    _T ("Rem"),
+    _T ("Right"),
+    _T ("RmDir"),
+    _T ("Rnd"),
+    _T ("Second"),
+    _T ("Seek"),
+    _T ("Seek"),
+    _T ("Select Case"),
+    _T ("SendKeys"),
+    _T ("Set"),
+    _T ("Shell"),
+    _T ("Sin"),
+    _T ("Space"),
+    _T ("Sqr"),
+    _T ("Static"),
+    _T ("Stop"),
+    _T ("Str"),
+    _T ("StrComp"),
+    _T ("String"),
+    _T ("StringFunction"),
+    _T ("Sub"),
+    _T ("Tan"),
+    _T ("Text"),
+    _T ("TextBox"),
+    _T ("Time"),
+    _T ("TimeSerial"),
+    _T ("TimeValue"),
+    _T ("Trim"),
+    _T ("LTrim"),
+    _T ("RTrim"),
+    _T ("Type"),
+    _T ("UBound"),
+    _T ("UCase"),
+    _T ("Val"),
+    _T ("VarType"),
+    _T ("While"),
+    _T ("Wend"),
+    _T ("With"),
+    _T ("Write"),
+    _T ("Year"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsncmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsBasicKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszBasicKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsBasicNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex) \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT      0x0001
+#define COOKIE_PREPROCESSOR   0x0002
+#define COOKIE_EXT_COMMENT    0x0004
+#define COOKIE_STRING     0x0008
+#define COOKIE_CHAR       0x0010
+
+DWORD CCrystalTextView::
+ParseLineBasic (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 2 && !xisalnum (pszChars[I]) && (pszChars[I - 1] == 'M' || pszChars[I - 1] == 'm') && (pszChars[I - 2] == 'E' || pszChars[I - 2] == 'e') && (pszChars[I - 3] == 'R' || pszChars[I - 3] == 'r'))
+        {
+          DEFINE_BLOCK (I - 3, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsBasicKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsBasicNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsBasicKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsBasicNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/batch.cpp b/Src/editlib/batch.cpp
new file mode 100644 (file)
index 0000000..a1b05a0
--- /dev/null
@@ -0,0 +1,443 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    batch.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  MS-DOS batch syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszBatKeywordList[] =
+  {
+    _T ("?"),
+    _T ("CALL"),
+    _T ("CD"),
+    _T ("CDD"),
+    _T ("CHCP"),
+    _T ("CLS"),
+    _T ("COLOR"),
+    _T ("COPY"),
+    _T ("CTTY"),
+    _T ("DATE"),
+    _T ("DEL"),
+    _T ("DELAY"),
+    _T ("DESCRIBE"),
+    _T ("DIR"),
+    _T ("DIRHISTORY"),
+    _T ("DIRS"),
+    _T ("DO"),
+    _T ("DRAWBOX"),
+    _T ("DRAWHLINE"),
+    _T ("DRAWVLINE"),
+    _T ("ECHO"),
+    _T ("ECHOERR"),
+    _T ("ECHOS"),
+    _T ("ECHOSERR"),
+    _T ("ENDLOCAL"),
+    _T ("ERASE"),
+    _T ("ESET"),
+    _T ("EXCEPT"),
+    _T ("EXIT"),
+    _T ("FFIND"),
+    _T ("FOR"),
+    _T ("FREE"),
+    _T ("GLOBAL"),
+    _T ("GOSUB"),
+    _T ("GOTO"),
+    _T ("HELP"),
+    _T ("HISTORY"),
+    _T ("IF"),
+    _T ("IFF"),
+    _T ("INKEY"),
+    _T ("INPUT"),
+    _T ("KEYBD"),
+    _T ("KEYSTACK"),
+    _T ("LH"),
+    _T ("LOADHIGH"),
+    _T ("LIST"),
+    _T ("LOADBTM"),
+    _T ("LOCK"),
+    _T ("LOG"),
+    _T ("MD"),
+    _T ("MKDIR"),
+    _T ("MEMORY"),
+    _T ("MOVE"),
+    _T ("ON"),
+    _T ("OPTION"),
+    _T ("PATH"),
+    _T ("PAUSE"),
+    _T ("POPD"),
+    _T ("PROMPT"),
+    _T ("PUSHD"),
+    _T ("QUIT"),
+    _T ("RD"),
+    _T ("REBOOT"),
+    _T ("REM"),
+    _T ("REN"),
+    _T ("RENAME"),
+    _T ("RETURN"),
+    _T ("SCREEN"),
+    _T ("SCRPUT"),
+    _T ("SELECT"),
+    _T ("SET"),
+    _T ("SETDOS"),
+    _T ("SETLOCAL"),
+    _T ("SHIFT"),
+    _T ("START"),
+    _T ("SWAPPING"),
+    _T ("SWITCH"),
+    _T ("TEE"),
+    _T ("TEXT"),
+    _T ("TIME"),
+    _T ("TIMER"),
+    _T ("TOUCH"),
+    _T ("TREE"),
+    _T ("TRUENAME"),
+    _T ("TYPE"),
+    _T ("UNALIAS"),
+    _T ("UNLOCK"),
+    _T ("UNSET"),
+    _T ("VER"),
+    _T ("VERIFY"),
+    _T ("VOL"),
+    _T ("VSCRPUT"),
+    _T ("Y"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("APPEND"),
+    _T ("ATTRIB"),
+    _T ("BUSETUP"),
+    _T ("CHKDSK"),
+    _T ("CHOICE"),
+    _T ("COMMAND"),
+    _T ("DEBUG"),
+    _T ("DEFRAG"),
+    _T ("DELOLDOS"),
+    _T ("DELTREE"),
+    _T ("DISKCOMP"),
+    _T ("DISKCOPY"),
+    _T ("DOSKEY"),
+    _T ("DRVSPACE"),
+    _T ("EDIT"),
+    _T ("EMM386"),
+    _T ("EXPAND"),
+    _T ("FASTHELP"),
+    _T ("FASTOPEN"),
+    _T ("FC"),
+    _T ("FDISK"),
+    _T ("FIND"),
+    _T ("FORMAT"),
+    _T ("GRAPHICS"),
+    _T ("HELP"),
+    _T ("INTERLNK"),
+    _T ("INTERSVR"),
+    _T ("KEYB"),
+    _T ("LABEL"),
+    _T ("LOADFIX"),
+    _T ("MEM"),
+    _T ("MEMMAKER"),
+    _T ("MODE"),
+    _T ("MORE"),
+    _T ("MOUSE"),
+    _T ("MOVE"),
+    _T ("MSAV"),
+    _T ("MSBACKUP"),
+    _T ("MSCDEX"),
+    _T ("MSD"),
+    _T ("MWAV"),
+    _T ("MWAVTSR"),
+    _T ("MWBACKUP"),
+    _T ("MWUNDEL"),
+    _T ("NLSFUNC"),
+    _T ("POWER"),
+    _T ("PRINT"),
+    _T ("QBASIC"),
+    _T ("REPLACE"),
+    _T ("RESTORE"),
+    _T ("SCANDISK"),
+    _T ("SETUP"),
+    _T ("SETVER"),
+    _T ("SHARE"),
+    _T ("SIZER"),
+    _T ("SMARTDRV"),
+    _T ("SMARTMON"),
+    _T ("SORT"),
+    _T ("SUBST"),
+    _T ("SYS"),
+    _T ("TREE"),
+    _T ("UNDELETE"),
+    _T ("UNFORMAT"),
+    _T ("UNINSTAL"),
+    _T ("VSAFE"),
+    _T ("XCOPY"),
+    NULL
+  };
+
+static BOOL
+IsBatKeyword (LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; s_apszBatKeywordList[L] != NULL; L++)
+    {
+      if (_tcsnicmp (s_apszBatKeywordList[L], pszChars, nLength) == 0
+            && s_apszBatKeywordList[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  TCHAR buffer[13];
+
+  for (int L = 0; s_apszUser1KeywordList[L] != NULL; L++)
+    {
+      if (_tcsnicmp (s_apszUser1KeywordList[L], pszChars, nLength) == 0
+            && s_apszUser1KeywordList[L][nLength] == 0)
+        return TRUE;
+      _tcscpy (buffer, s_apszUser1KeywordList[L]);
+      _tcscat (buffer, _T (".COM"));
+      if (_tcsnicmp (buffer, pszChars, nLength) == 0
+            && buffer[nLength] == 0)
+        return TRUE;
+      _tcscpy (buffer, s_apszUser1KeywordList[L]);
+      _tcscat (buffer, _T (".EXE"));
+      if (_tcsnicmp (buffer, pszChars, nLength) == 0
+            && buffer[nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsBatNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineBatch (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (pszChars[I] == ':')
+            {
+              DEFINE_BLOCK (I, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              continue;
+            }
+          if (nLength >= I + 3 && !_tcsnicmp (pszChars + I, _T ("REM"), 3) && (isspace (pszChars[I + 3]) || nLength == I + 3))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+              dwCookie |= COOKIE_COMMENT;
+              break;
+            }
+
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsBatKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsBatNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsBatKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsBatNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+    }
+
+  dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/ccrystaleditview.cpp b/Src/editlib/ccrystaleditview.cpp
new file mode 100644 (file)
index 0000000..1233ac7
--- /dev/null
@@ -0,0 +1,2532 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:       ccrystaleditview.cpp
+//  Version:    1.2.0.5
+//  Created:    29-Dec-1998
+//
+//  Copyright:  Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CCrystalEditView class, a part of the Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  21-Feb-99
+//      Paul Selormey, James R. Twine:
+//  +   FEATURE: description for Undo/Redo actions
+//  +   FEATURE: multiple MSVC-like bookmarks
+//  +   FEATURE: 'Disable backspace at beginning of line' option
+//  +   FEATURE: 'Disable drag-n-drop editing' option
+//
+//  +   FEATURE: Auto indent
+//  +   FIX: ResetView() was overriden to provide cleanup
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: support for autoindenting brackets and parentheses
+//  +   FEATURE: menu options, view and window
+//  +   FEATURE: SDI+MDI versions with help
+//  +   FEATURE: extended registry support for saving settings
+//  +   FEATURE: some other things I've forgotten ...
+//  27-Jul-99
+//  +   FIX: treating groups in regular expressions corrected
+//  +   FIX: autocomplete corrected
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//     ??-Aug-99
+//             Sven Wiegand (search for "//BEGIN SW" to find my changes):
+//     + FEATURE: "Go to last change" (sets the cursor on the position where
+//                     the user did his last edit actions
+//     + FEATURE: Support for incremental search in CCrystalTextView
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//     24-Oct-99
+//             Sven Wiegand
+//     + FEATURE: Supporting [Return] to exit incremental-search-mode
+//                  (see OnChar())
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "editcmd.h"
+#include "editreg.h"
+#include "ccrystaleditview.h"
+#include "ccrystaltextbuffer.h"
+#include "ceditreplacedlg.h"
+#include "registry.h"
+#include "cs2cs.h"
+#include "chcondlg.h"
+
+#ifndef __AFXPRIV_H__
+#pragma message("Include <afxpriv.h> in your stdafx.h to avoid this message")
+#include <afxpriv.h>
+#endif
+#ifndef __AFXOLE_H__
+#pragma message("Include <afxole.h> in your stdafx.h to avoid this message")
+#include <afxole.h>
+#endif
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define DRAG_BORDER_X       5
+#define DRAG_BORDER_Y       5
+
+/////////////////////////////////////////////////////////////////////////////
+// CEditDropTargetImpl class declaration
+
+class CEditDropTargetImpl : public COleDropTarget
+  {
+private :
+    CCrystalEditView * m_pOwner;
+public :
+    CEditDropTargetImpl (CCrystalEditView * pOwner)
+    {
+      m_pOwner = pOwner;
+    };
+
+    virtual DROPEFFECT OnDragEnter (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point);
+    virtual void OnDragLeave (CWnd * pWnd);
+    virtual DROPEFFECT OnDragOver (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point);
+    virtual BOOL OnDrop (CWnd * pWnd, COleDataObject * pDataObject, DROPEFFECT dropEffect, CPoint point);
+    virtual DROPEFFECT OnDragScroll (CWnd * pWnd, DWORD dwKeyState, CPoint point);
+  };
+
+
+#pragma warning ( disable : 4100 )
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalEditView
+
+IMPLEMENT_DYNCREATE (CCrystalEditView, CCrystalTextView)
+
+CCrystalEditView::CCrystalEditView ()
+{
+  AFX_ZERO_INIT_OBJECT (CCrystalTextView);
+  m_bInsertTabs = TRUE;
+  m_bAutoIndent = TRUE;
+  m_mapExpand = new CMap<CString, LPCTSTR, CString, LPCTSTR> (10);
+}
+
+CCrystalEditView:: ~ CCrystalEditView ()
+{
+  delete m_mapExpand;
+}
+
+bool CCrystalEditView::
+DoSetTextType (TextDefinition *def)
+{
+  m_CurSourceDef = def;
+  SetInsertTabs ((def->flags & SRCOPT_INSERTTABS) != FALSE);
+  SetAutoIndent ((def->flags & SRCOPT_AUTOINDENT) != FALSE);
+  SetDisableBSAtSOL ((def->flags & SRCOPT_BSATBOL) == FALSE);
+  m_mapExpand->RemoveAll ();
+  CReg reg;
+  CString sKey = REG_EDITPAD _T("\\");
+  sKey += def->name;
+  sKey += _T ("\\Expand");
+  if (reg.Open (HKEY_CURRENT_USER, sKey, KEY_READ))
+    {
+      LPCTSTR pszValue;
+      RegVal regVal;
+      if (reg.FindFirstValue (pszValue, &regVal))
+        {
+          CString sData;
+          do
+            if (RegValGetString (&regVal, sData))
+              m_mapExpand->SetAt (pszValue, sData);
+          while (reg.FindNextValue (pszValue, &regVal));
+        }
+      reg.FindClose ();
+    }
+  return CCrystalTextView::DoSetTextType (def);
+}
+
+BEGIN_MESSAGE_MAP (CCrystalEditView, CCrystalTextView)
+//{{AFX_MSG_MAP(CCrystalEditView)
+ON_COMMAND (ID_EDIT_PASTE, OnEditPaste)
+ON_UPDATE_COMMAND_UI (ID_EDIT_CUT, OnUpdateEditCut)
+ON_COMMAND (ID_EDIT_CUT, OnEditCut)
+ON_UPDATE_COMMAND_UI (ID_EDIT_PASTE, OnUpdateEditPaste)
+ON_COMMAND (ID_EDIT_DELETE, OnEditDelete)
+ON_WM_CHAR ()
+ON_COMMAND (ID_EDIT_DELETE_BACK, OnEditDeleteBack)
+ON_COMMAND (ID_EDIT_UNTAB, OnEditUntab)
+ON_COMMAND (ID_EDIT_TAB, OnEditTab)
+ON_COMMAND (ID_EDIT_SWITCH_OVRMODE, OnEditSwitchOvrmode)
+ON_UPDATE_COMMAND_UI (ID_EDIT_SWITCH_OVRMODE, OnUpdateEditSwitchOvrmode)
+ON_WM_CREATE ()
+ON_WM_DESTROY ()
+ON_COMMAND (ID_EDIT_REPLACE, OnEditReplace)
+ON_UPDATE_COMMAND_UI (ID_EDIT_UNDO, OnUpdateEditUndo)
+ON_COMMAND (ID_EDIT_UNDO, OnEditUndo)
+ON_UPDATE_COMMAND_UI (ID_EDIT_REDO, OnUpdateEditRedo)
+ON_COMMAND (ID_EDIT_REDO, OnEditRedo)
+ON_UPDATE_COMMAND_UI (ID_EDIT_AUTOCOMPLETE, OnUpdateEditAutoComplete)
+ON_COMMAND (ID_EDIT_AUTOCOMPLETE, OnEditAutoComplete)
+ON_UPDATE_COMMAND_UI (ID_EDIT_AUTOEXPAND, OnUpdateEditAutoExpand)
+ON_COMMAND (ID_EDIT_AUTOEXPAND, OnEditAutoExpand)
+ON_UPDATE_COMMAND_UI (ID_EDIT_LOWERCASE, OnUpdateEditLowerCase)
+ON_COMMAND (ID_EDIT_LOWERCASE, OnEditLowerCase)
+ON_UPDATE_COMMAND_UI (ID_EDIT_UPPERCASE, OnUpdateEditUpperCase)
+ON_COMMAND (ID_EDIT_UPPERCASE, OnEditUpperCase)
+ON_UPDATE_COMMAND_UI (ID_EDIT_SWAPCASE, OnUpdateEditSwapCase)
+ON_COMMAND (ID_EDIT_SWAPCASE, OnEditSwapCase)
+ON_UPDATE_COMMAND_UI (ID_EDIT_SWAPCASE, OnUpdateEditSwapCase)
+ON_COMMAND (ID_EDIT_SWAPCASE, OnEditSwapCase)
+ON_UPDATE_COMMAND_UI (ID_EDIT_CAPITALIZE, OnUpdateEditCapitalize)
+ON_COMMAND (ID_EDIT_CAPITALIZE, OnEditCapitalize)
+ON_UPDATE_COMMAND_UI (ID_EDIT_SENTENCE, OnUpdateEditSentence)
+ON_COMMAND (ID_EDIT_SENTENCE, OnEditSentence)
+ON_UPDATE_COMMAND_UI(ID_EDIT_GOTO_LAST_CHANGE, OnUpdateEditGotoLastChange)
+ON_COMMAND(ID_EDIT_GOTO_LAST_CHANGE, OnEditGotoLastChange)
+ON_COMMAND(ID_EDIT_DELETE_WORD, OnEditDeleteWord)
+ON_COMMAND(ID_EDIT_DELETE_WORD_BACK, OnEditDeleteWordBack)
+//}}AFX_MSG_MAP
+ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_READ, OnUpdateIndicatorRead)
+ON_UPDATE_COMMAND_UI (ID_INDICATOR_OVR, OnUpdateIndicatorOvr)
+ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_POSITION, OnUpdateIndicatorPosition)
+ON_UPDATE_COMMAND_UI (ID_TOOLS_SPELLING, OnUpdateToolsSpelling)
+ON_COMMAND (ID_TOOLS_SPELLING, OnToolsSpelling)
+ON_UPDATE_COMMAND_UI (ID_TOOLS_CHARCODING, OnUpdateToolsCharCoding)
+ON_COMMAND (ID_TOOLS_CHARCODING, OnToolsCharCoding)
+END_MESSAGE_MAP ()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalEditView message handlers
+
+void CCrystalEditView::ResetView ()
+{
+  // m_bAutoIndent = TRUE;
+  m_bOvrMode = FALSE;
+  m_bLastReplace = FALSE;
+  CCrystalTextView::ResetView ();
+}
+
+BOOL CCrystalEditView::
+QueryEditable ()
+{
+  if (m_pTextBuffer == NULL)
+    return FALSE;
+  return !m_pTextBuffer->GetReadOnly ();
+}
+
+void CCrystalEditView::
+OnEditPaste ()
+{
+  Paste ();
+}
+
+void CCrystalEditView::
+OnUpdateEditPaste (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (TextInClipboard ());
+}
+
+void CCrystalEditView::
+OnUpdateEditCut (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (IsSelection ());
+}
+
+void CCrystalEditView::
+OnEditCut ()
+{
+  Cut ();
+}
+
+BOOL CCrystalEditView::
+DeleteCurrentSelection ()
+{
+  if (IsSelection ())
+    {
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+
+      CPoint ptCursorPos = ptSelStart;
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      SetAnchor (ptCursorPos);
+      SetSelection (ptCursorPos, ptCursorPos);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+
+      // [JRT]:
+      m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELSEL);
+      return TRUE;
+    }
+  return FALSE;
+}
+
+void CCrystalEditView::
+Paste ()
+{
+  if (!QueryEditable ())
+    return;
+  if (m_pTextBuffer == NULL)
+    return;
+
+  CString text;
+  if (GetFromClipboard (text))
+    {
+      m_pTextBuffer->BeginUndoGroup ();
+    
+      CPoint ptCursorPos;
+      if (IsSelection ())
+        {
+          CPoint ptSelStart, ptSelEnd;
+          GetSelection (ptSelStart, ptSelEnd);
+    
+          ptCursorPos = ptSelStart;
+          /*SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);*/
+
+                 // WINMERGE: clear the winmerge flags so the file saves correctly
+                 for (int i=ptSelStart.y; i <= ptSelEnd.y; i++)
+                        m_pTextBuffer->SetLineFlag(i, LF_WINMERGE_FLAGS, FALSE, FALSE, FALSE);
+    
+          // [JRT]:
+          m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_PASTE);
+        }
+      else
+         {
+        ptCursorPos = GetCursorPos ();
+                 
+               // WINMERGE: clear the winmerge flags so the file saves correctly
+               m_pTextBuffer->SetLineFlag(ptCursorPos.y, LF_WINMERGE_FLAGS, FALSE, FALSE, FALSE);
+         }
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      
+      int x, y;
+      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, y, x, CE_ACTION_PASTE);  //  [JRT]
+
+      ptCursorPos.x = x;
+      ptCursorPos.y = y;
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      SetAnchor (ptCursorPos);
+      SetSelection (ptCursorPos, ptCursorPos);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+void CCrystalEditView::
+Cut ()
+{
+  if (!QueryEditable ())
+    return;
+  if (m_pTextBuffer == NULL)
+    return;
+  if (!IsSelection ())
+    return;
+
+  CPoint ptSelStart, ptSelEnd;
+  GetSelection (ptSelStart, ptSelEnd);
+  CString text;
+  GetText (ptSelStart, ptSelEnd, text);
+  PutToClipboard (text);
+
+  CPoint ptCursorPos = ptSelStart;
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+  SetAnchor (ptCursorPos);
+  SetSelection (ptCursorPos, ptCursorPos);
+  SetCursorPos (ptCursorPos);
+  EnsureVisible (ptCursorPos);
+
+  m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_CUT);  // [JRT]
+
+}
+
+void CCrystalEditView::
+OnEditDelete ()
+{
+  if (!QueryEditable () || m_pTextBuffer == NULL)
+    return;
+
+  CPoint ptSelStart, ptSelEnd;
+  GetSelection (ptSelStart, ptSelEnd);
+  if (ptSelStart == ptSelEnd)
+    {
+      if (ptSelEnd.x == GetLineLength (ptSelEnd.y))
+        {
+          if (ptSelEnd.y == GetLineCount () - 1)
+            return;
+          ptSelEnd.y++;
+          ptSelEnd.x = 0;
+        }
+      else
+        ptSelEnd.x++;
+    }
+
+  CPoint ptCursorPos = ptSelStart;
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+  SetAnchor (ptCursorPos);
+  SetSelection (ptCursorPos, ptCursorPos);
+  SetCursorPos (ptCursorPos);
+  EnsureVisible (ptCursorPos);
+
+  m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE);   // [JRT]
+
+}
+
+void CCrystalEditView::
+OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+  //BEGIN SW
+  // check if incremental search is active before call to CCrystalTextView::OnChar()
+  BOOL bIncrementalSearch = m_bIncrementalSearchForward || m_bIncrementalSearchBackward;
+  //END Sw
+  CCrystalTextView::OnChar (nChar, nRepCnt, nFlags);
+       //BEGIN SW
+       // if we are in incremental search mode ignore the character
+       if( m_bIncrementalSearchForward || m_bIncrementalSearchBackward )
+               return;
+       //END SW
+
+  // if we *were* in incremental search mode and CCrystalTextView::OnChar()
+  // exited it the ignore the character (VK_RETURN)
+  if( bIncrementalSearch && !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
+    return;
+  //END SW
+
+  if ((::GetAsyncKeyState (VK_LBUTTON) & 0x8000) != 0 ||
+        (::GetAsyncKeyState (VK_RBUTTON) & 0x8000) != 0)
+    return;
+
+  if (nChar == VK_RETURN)
+    {
+      if (m_bOvrMode)
+        {
+          CPoint ptCursorPos = GetCursorPos ();
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          if (ptCursorPos.y < GetLineCount () - 1)
+            {
+              ptCursorPos.x = 0;
+              ptCursorPos.y++;
+
+              ASSERT_VALIDTEXTPOS (ptCursorPos);
+              SetSelection (ptCursorPos, ptCursorPos);
+              SetAnchor (ptCursorPos);
+              SetCursorPos (ptCursorPos);
+              EnsureVisible (ptCursorPos);
+              return;
+            }
+        }
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      if (QueryEditable () && m_pTextBuffer != NULL)
+        {
+          CPoint ptCursorPos;
+          if (IsSelection ())
+            {
+              CPoint ptSelStart, ptSelEnd;
+              GetSelection (ptSelStart, ptSelEnd);
+        
+              ptCursorPos = ptSelStart;
+              /*SetAnchor (ptCursorPos);
+              SetSelection (ptCursorPos, ptCursorPos);
+              SetCursorPos (ptCursorPos);
+              EnsureVisible (ptCursorPos);*/
+        
+              // [JRT]:
+              m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_TYPING);
+            }
+          else
+            ptCursorPos = GetCursorPos ();
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          const static TCHAR pszText[3] = _T ("\r\n");
+
+          int x, y;
+          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING);  //  [JRT]
+
+          ptCursorPos.x = x;
+          ptCursorPos.y = y;
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+        }
+
+      m_pTextBuffer->FlushUndoGroup (this);
+      return;
+    }
+
+  if (nChar > 31)
+    {
+      if (QueryEditable () && m_pTextBuffer != NULL)
+        {
+          m_pTextBuffer->BeginUndoGroup (nChar != _T (' '));
+
+          CPoint ptSelStart, ptSelEnd;
+          GetSelection (ptSelStart, ptSelEnd);
+          CPoint ptCursorPos;
+          if (ptSelStart != ptSelEnd)
+            {
+              ptCursorPos = ptSelStart;
+              if (IsSelection ())
+                {
+                  CPoint ptSelStart, ptSelEnd;
+                  GetSelection (ptSelStart, ptSelEnd);
+            
+                  /*SetAnchor (ptCursorPos);
+                  SetSelection (ptCursorPos, ptCursorPos);
+                  SetCursorPos (ptCursorPos);
+                  EnsureVisible (ptCursorPos);*/
+            
+                  // [JRT]:
+                  m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_TYPING);
+                }
+            }
+          else
+            {
+              ptCursorPos = GetCursorPos ();
+              if (m_bOvrMode && ptCursorPos.x < GetLineLength (ptCursorPos.y))
+                m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCursorPos.y, ptCursorPos.x + 1, CE_ACTION_TYPING);     // [JRT]
+
+            }
+
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+
+          TCHAR pszText[2];
+          pszText[0] = (TCHAR) nChar;
+          pszText[1] = 0;
+
+          int x, y;
+          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING);    // [JRT]
+
+          ptCursorPos.x = x;
+          ptCursorPos.y = y;
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+
+          m_pTextBuffer->FlushUndoGroup (this);
+        }
+    }
+}
+
+
+//
+//  [JRT]: Added Support For "Disable Backspace At Start Of Line"
+//
+void CCrystalEditView::
+OnEditDeleteBack ()
+{
+       //BEGIN SW
+       // if we are in incremental search mode ignore backspace
+       CCrystalTextView::OnEditDeleteBack();
+       if( m_bIncrementalSearchForward || m_bIncrementalSearchBackward )
+               return;
+       //END SW
+
+  if (IsSelection ())
+    {
+      OnEditDelete ();
+      return;
+    }
+
+  if (!QueryEditable () || m_pTextBuffer == NULL)
+    return;
+
+  CPoint ptCursorPos = GetCursorPos ();
+  CPoint ptCurrentCursorPos = ptCursorPos;
+  bool bDeleted = false;
+
+  if (!(ptCursorPos.x))         // If At Start Of Line
+
+    {
+      if (!m_bDisableBSAtSOL)   // If DBSASOL Is Disabled
+
+        {
+          if (ptCursorPos.y > 0)    // If Previous Lines Available
+
+            {
+              ptCursorPos.y--;  // Decrement To Previous Line
+
+              ptCursorPos.x = GetLineLength (
+                                ptCursorPos.y);   // Set Cursor To End Of Previous Line
+
+              bDeleted = true;  // Set Deleted Flag
+
+            }
+        }
+    }
+  else                          // If Caret Not At SOL
+
+    {
+      ptCursorPos.x--;          // Decrement Position
+
+      bDeleted = true;          // Set Deleted Flag
+
+    }
+  /*
+     if (ptCursorPos.x == 0)
+     {
+     if (ptCursorPos.y == 0)
+     return;
+     ptCursorPos.y --;
+     ptCursorPos.x = GetLineLength(ptCursorPos.y);
+     }
+     else
+     ptCursorPos.x --;
+   */
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+  SetAnchor (ptCursorPos);
+  SetSelection (ptCursorPos, ptCursorPos);
+  SetCursorPos (ptCursorPos);
+  EnsureVisible (ptCursorPos);
+
+  if (bDeleted)
+    {
+      m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCurrentCursorPos.y, ptCurrentCursorPos.x, CE_ACTION_BACKSPACE);  // [JRT]
+
+    }
+  return;
+}
+
+void CCrystalEditView::
+OnEditTab ()
+{
+  if (!QueryEditable () || m_pTextBuffer == NULL)
+    return;
+
+  BOOL bTabify = FALSE;
+  CPoint ptSelStart, ptSelEnd;
+  if (IsSelection ())
+    {
+      GetSelection (ptSelStart, ptSelEnd);
+      bTabify = ptSelStart.y != ptSelEnd.y;
+    }
+
+  CPoint ptCursorPos = GetCursorPos ();
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+
+  static TCHAR pszText[32];
+  if (m_bInsertTabs)
+    {
+      *pszText = _T ('\t');
+      pszText[1] = _T ('\0');
+    }
+  else
+    {
+      int nTabSize = GetTabSize ();
+      int nChars = nTabSize - ptCursorPos.x % nTabSize;
+      memset(pszText, _T(' '), nChars);
+      pszText[nChars] = _T ('\0');
+    }
+
+  if (bTabify)
+    {
+      m_pTextBuffer->BeginUndoGroup ();
+
+      int nStartLine = ptSelStart.y;
+      int nEndLine = ptSelEnd.y;
+      ptSelStart.x = 0;
+      if (ptSelEnd.x > 0)
+        {
+          if (ptSelEnd.y == GetLineCount () - 1)
+            {
+              ptSelEnd.x = GetLineLength (ptSelEnd.y);
+            }
+          else
+            {
+              ptSelEnd.x = 0;
+              ptSelEnd.y++;
+            }
+        }
+      else
+        nEndLine--;
+      SetSelection (ptSelStart, ptSelEnd);
+      SetCursorPos (ptSelEnd);
+      EnsureVisible (ptSelEnd);
+
+      //  Shift selection to right
+      m_bHorzScrollBarLocked = TRUE;
+      for (int L = nStartLine; L <= nEndLine; L++)
+        {
+          int x, y;
+          m_pTextBuffer->InsertText (this, L, 0, pszText, y, x, CE_ACTION_INDENT);  //  [JRT]
+
+        }
+      m_bHorzScrollBarLocked = FALSE;
+      RecalcHorzScrollBar ();
+
+      m_pTextBuffer->FlushUndoGroup (this);
+      return;
+    }
+
+  if (m_bOvrMode)
+    {
+      CPoint ptCursorPos = GetCursorPos ();
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+
+      int nLineLength = GetLineLength (ptCursorPos.y);
+      LPCTSTR pszLineChars = GetLineChars (ptCursorPos.y);
+      if (ptCursorPos.x < nLineLength)
+        {
+          int nTabSize = GetTabSize ();
+          int nChars = nTabSize - CalculateActualOffset (ptCursorPos.y, ptCursorPos.x) % nTabSize;
+          ASSERT (nChars > 0 && nChars <= nTabSize);
+
+          while (nChars > 0)
+            {
+              if (ptCursorPos.x == nLineLength)
+                break;
+              if (pszLineChars[ptCursorPos.x] == _T ('\t'))
+                {
+                  ptCursorPos.x++;
+                  break;
+                }
+              ptCursorPos.x++;
+              nChars--;
+            }
+          ASSERT (ptCursorPos.x <= nLineLength);
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+          return;
+        }
+    }
+
+  m_pTextBuffer->BeginUndoGroup ();
+
+  if (IsSelection ())
+    {
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+
+      /*SetAnchor (ptCursorPos);
+      SetSelection (ptCursorPos, ptCursorPos);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);*/
+
+      // [JRT]:
+      m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_TYPING);
+    }
+
+  int x, y;
+  m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, y, x, CE_ACTION_TYPING);  //  [JRT]
+
+  ptCursorPos.x = x;
+  ptCursorPos.y = y;
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+  SetSelection (ptCursorPos, ptCursorPos);
+  SetAnchor (ptCursorPos);
+  SetCursorPos (ptCursorPos);
+  EnsureVisible (ptCursorPos);
+
+  m_pTextBuffer->FlushUndoGroup (this);
+}
+
+void CCrystalEditView::
+OnEditUntab ()
+{
+  if (!QueryEditable () || m_pTextBuffer == NULL)
+    return;
+
+  BOOL bTabify = FALSE;
+  CPoint ptSelStart, ptSelEnd;
+  if (IsSelection ())
+    {
+      GetSelection (ptSelStart, ptSelEnd);
+      bTabify = ptSelStart.y != ptSelEnd.y;
+    }
+
+  if (bTabify)
+    {
+      m_pTextBuffer->BeginUndoGroup ();
+
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      int nStartLine = ptSelStart.y;
+      int nEndLine = ptSelEnd.y;
+      ptSelStart.x = 0;
+      if (ptSelEnd.x > 0)
+        {
+          if (ptSelEnd.y == GetLineCount () - 1)
+            {
+              ptSelEnd.x = GetLineLength (ptSelEnd.y);
+            }
+          else
+            {
+              ptSelEnd.x = 0;
+              ptSelEnd.y++;
+            }
+        }
+      else
+        nEndLine--;
+      SetSelection (ptSelStart, ptSelEnd);
+      SetCursorPos (ptSelEnd);
+      EnsureVisible (ptSelEnd);
+
+      //  Shift selection to left
+      m_bHorzScrollBarLocked = TRUE;
+      for (int L = nStartLine; L <= nEndLine; L++)
+        {
+          int nLength = GetLineLength (L);
+          if (nLength > 0)
+            {
+              LPCTSTR pszChars = GetLineChars (L);
+              int nPos = 0, nOffset = 0;
+              while (nPos < nLength)
+                {
+                  if (pszChars[nPos] == _T (' '))
+                    {
+                      nPos++;
+                      if (++nOffset >= GetTabSize ())
+                        break;
+                    }
+                  else
+                    {
+                      if (pszChars[nPos] == _T ('\t'))
+                        nPos++;
+                      break;
+                    }
+                }
+
+              if (nPos > 0)
+                m_pTextBuffer->DeleteText (this, L, 0, L, nPos, CE_ACTION_INDENT);  // [JRT]
+
+            }
+        }
+      m_bHorzScrollBarLocked = FALSE;
+      RecalcHorzScrollBar ();
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+  else
+    {
+      CPoint ptCursorPos = GetCursorPos ();
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      if (ptCursorPos.x > 0)
+        {
+          int nTabSize = GetTabSize ();
+          int nOffset = CalculateActualOffset (ptCursorPos.y, ptCursorPos.x);
+          int nNewOffset = nOffset / nTabSize * nTabSize;
+          if (nOffset == nNewOffset && nNewOffset > 0)
+            nNewOffset -= nTabSize;
+          ASSERT (nNewOffset >= 0);
+
+          LPCTSTR pszChars = GetLineChars (ptCursorPos.y);
+          int nCurrentOffset = 0;
+          int I = 0;
+          while (nCurrentOffset < nNewOffset)
+            {
+              if (pszChars[I] == _T ('\t'))
+                nCurrentOffset = nCurrentOffset / nTabSize * nTabSize + nTabSize;
+              else
+                nCurrentOffset++;
+              I++;
+            }
+
+          ASSERT (nCurrentOffset == nNewOffset);
+
+          ptCursorPos.x = I;
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+        }
+    }
+}
+
+void CCrystalEditView::
+OnUpdateIndicatorCol (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (FALSE);
+}
+
+void CCrystalEditView::
+OnUpdateIndicatorOvr (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (m_bOvrMode);
+}
+
+void CCrystalEditView::
+OnUpdateIndicatorRead (CCmdUI * pCmdUI)
+{
+  if (m_pTextBuffer == NULL)
+    pCmdUI->Enable (FALSE);
+  else
+    pCmdUI->Enable (m_pTextBuffer->GetReadOnly ());
+}
+
+void CCrystalEditView::
+OnEditSwitchOvrmode ()
+{
+  m_bOvrMode = !m_bOvrMode;
+}
+
+void CCrystalEditView::
+OnUpdateEditSwitchOvrmode (CCmdUI * pCmdUI)
+{
+  pCmdUI->SetCheck (m_bOvrMode ? 1 : 0);
+}
+
+DROPEFFECT CEditDropTargetImpl::
+OnDragEnter (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
+{
+  if (!pDataObject->IsDataAvailable (CF_TEXT))
+    {
+      m_pOwner->HideDropIndicator ();
+      return DROPEFFECT_NONE;
+    }
+  m_pOwner->ShowDropIndicator (point);
+  if (dwKeyState & MK_CONTROL)
+    return DROPEFFECT_COPY;
+  return DROPEFFECT_MOVE;
+}
+
+void CEditDropTargetImpl::
+OnDragLeave (CWnd * pWnd)
+{
+  m_pOwner->HideDropIndicator ();
+}
+
+DROPEFFECT CEditDropTargetImpl::
+OnDragOver (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
+{
+  /*
+     if (! pDataObject->IsDataAvailable(CF_TEXT))
+     {
+     m_pOwner->HideDropIndicator();
+     return DROPEFFECT_NONE;
+     }
+   */
+  //
+  // [JRT]
+  //
+  bool bDataSupported = false;
+
+  if ((!m_pOwner) ||            // If No Owner
+        (!(m_pOwner->QueryEditable ())) ||   // Or Not Editable
+        (m_pOwner->GetDisableDragAndDrop ()))    // Or Drag And Drop Disabled
+
+    {
+      m_pOwner->HideDropIndicator ();   // Hide Drop Caret
+
+      return DROPEFFECT_NONE;   // Return DE_NONE
+
+    }
+  //  if ((pDataObject->IsDataAvailable( CF_TEXT ) ) ||       // If Text Available
+  //          ( pDataObject -> IsDataAvailable( xxx ) ) ||    // Or xxx Available
+  //          ( pDataObject -> IsDataAvailable( yyy ) ) )     // Or yyy Available
+  if (pDataObject->IsDataAvailable (CF_TEXT))   // If Text Available
+
+    {
+      bDataSupported = true;    // Set Flag
+
+    }
+  if (!bDataSupported)          // If No Supported Formats Available
+
+    {
+      m_pOwner->HideDropIndicator ();   // Hide Drop Caret
+
+      return DROPEFFECT_NONE;   // Return DE_NONE
+
+    }
+  m_pOwner->ShowDropIndicator (point);
+  if (dwKeyState & MK_CONTROL)
+    return DROPEFFECT_COPY;
+  return DROPEFFECT_MOVE;
+}
+
+BOOL CEditDropTargetImpl::
+OnDrop (CWnd * pWnd, COleDataObject * pDataObject, DROPEFFECT dropEffect, CPoint point)
+{
+  //
+  // [JRT]            ( m_pOwner -> GetDisableDragAndDrop() ) )       // Or Drag And Drop Disabled
+  //
+  bool bDataSupported = false;
+
+  m_pOwner->HideDropIndicator ();   // Hide Drop Caret
+
+  if ((!m_pOwner) ||            // If No Owner
+        (!(m_pOwner->QueryEditable ())) ||   // Or Not Editable
+        (m_pOwner->GetDisableDragAndDrop ()))    // Or Drag And Drop Disabled
+
+    {
+      return DROPEFFECT_NONE;   // Return DE_NONE
+
+    }
+  //  if( ( pDataObject -> IsDataAvailable( CF_TEXT ) ) ||    // If Text Available
+  //          ( pDataObject -> IsDataAvailable( xxx ) ) ||    // Or xxx Available
+  //          ( pDataObject -> IsDataAvailable( yyy ) ) )     // Or yyy Available
+  if (pDataObject->IsDataAvailable (CF_TEXT))   // If Text Available
+
+    {
+      bDataSupported = true;    // Set Flag
+
+    }
+  if (!bDataSupported)          // If No Supported Formats Available
+
+    {
+      return DROPEFFECT_NONE;   // Return DE_NONE
+
+    }
+  return (m_pOwner->DoDropText (pDataObject, point));   // Return Result Of Drop
+
+}
+
+DROPEFFECT CEditDropTargetImpl::
+OnDragScroll (CWnd * pWnd, DWORD dwKeyState, CPoint point)
+{
+  ASSERT (m_pOwner == pWnd);
+  m_pOwner->DoDragScroll (point);
+
+  if (dwKeyState & MK_CONTROL)
+    return DROPEFFECT_COPY;
+  return DROPEFFECT_MOVE;
+}
+
+void CCrystalEditView::
+DoDragScroll (const CPoint & point)
+{
+  CRect rcClientRect;
+  GetClientRect (rcClientRect);
+  if (point.y < rcClientRect.top + DRAG_BORDER_Y)
+    {
+      HideDropIndicator ();
+      ScrollUp ();
+      UpdateWindow ();
+      ShowDropIndicator (point);
+         //UpdateSiblingScrollPos(FALSE);
+      return;
+    }
+  if (point.y >= rcClientRect.bottom - DRAG_BORDER_Y)
+    {
+      HideDropIndicator ();
+      ScrollDown ();
+      UpdateWindow ();
+      ShowDropIndicator (point);
+         //UpdateSiblingScrollPos(FALSE);
+      return;
+    }
+  if (point.x < rcClientRect.left + GetMarginWidth () + DRAG_BORDER_X)
+    {
+      HideDropIndicator ();
+      ScrollLeft ();
+      UpdateWindow ();
+      ShowDropIndicator (point);
+         //UpdateSiblingScrollPos(TRUE);
+      return;
+    }
+  if (point.x >= rcClientRect.right - DRAG_BORDER_X)
+    {
+      HideDropIndicator ();
+      ScrollRight ();
+      UpdateWindow ();
+      ShowDropIndicator (point);
+         //UpdateSiblingScrollPos(TRUE);
+      return;
+    }
+}
+
+BOOL CCrystalEditView::
+DoDropText (COleDataObject * pDataObject, const CPoint & ptClient)
+{
+  HGLOBAL hData = pDataObject->GetGlobalData (CF_TEXT);
+  if (hData == NULL)
+    return FALSE;
+
+  CPoint ptDropPos = ClientToText (ptClient);
+  if (IsDraggingText () && IsInsideSelection (ptDropPos))
+    {
+      SetAnchor (ptDropPos);
+      SetSelection (ptDropPos, ptDropPos);
+      SetCursorPos (ptDropPos);
+      EnsureVisible (ptDropPos);
+      return FALSE;
+    }
+
+  LPTSTR pszText = (LPTSTR)::GlobalLock (hData);
+  if (pszText == NULL)
+    return FALSE;
+
+  int x, y;
+  m_pTextBuffer->InsertText (this, ptDropPos.y, ptDropPos.x, pszText, y, x, CE_ACTION_DRAGDROP);  //   [JRT]
+
+  CPoint ptCurPos (x, y);
+  ASSERT_VALIDTEXTPOS (ptCurPos);
+  SetAnchor (ptDropPos);
+  SetSelection (ptDropPos, ptCurPos);
+  SetCursorPos (ptCurPos);
+  EnsureVisible (ptCurPos);
+
+  ::GlobalUnlock (hData);
+  return TRUE;
+}
+
+int CCrystalEditView::
+OnCreate (LPCREATESTRUCT lpCreateStruct)
+{
+  if (CCrystalTextView::OnCreate (lpCreateStruct) == -1)
+    return -1;
+
+  ASSERT (m_pDropTarget == NULL);
+  m_pDropTarget = new CEditDropTargetImpl (this);
+  if (!m_pDropTarget->Register (this))
+    {
+      TRACE0 ("Warning: Unable to register drop target for ccrystaleditview.\n");
+      delete m_pDropTarget;
+      m_pDropTarget = NULL;
+    }
+
+  return 0;
+}
+
+void CCrystalEditView::
+OnDestroy ()
+{
+  if (m_pDropTarget != NULL)
+    {
+      m_pDropTarget->Revoke ();
+      delete m_pDropTarget;
+      m_pDropTarget = NULL;
+    }
+
+  CCrystalTextView::OnDestroy ();
+}
+
+void CCrystalEditView::
+ShowDropIndicator (const CPoint & point)
+{
+  if (!m_bDropPosVisible)
+    {
+      HideCursor ();
+      m_ptSavedCaretPos = GetCursorPos ();
+      m_bDropPosVisible = TRUE;
+      ::CreateCaret (m_hWnd, (HBITMAP) 1, 2, GetLineHeight ());
+    }
+  m_ptDropPos = ClientToText (point);
+  if (m_ptDropPos.x >= m_nOffsetChar)
+    {
+      SetCaretPos (TextToClient (m_ptDropPos));
+      ShowCaret ();
+    }
+  else
+    {
+      HideCaret ();
+    }
+}
+
+void CCrystalEditView::
+HideDropIndicator ()
+{
+  if (m_bDropPosVisible)
+    {
+      SetCursorPos (m_ptSavedCaretPos);
+      ShowCursor ();
+      m_bDropPosVisible = FALSE;
+    }
+}
+
+DROPEFFECT CCrystalEditView::
+GetDropEffect ()
+{
+  return DROPEFFECT_COPY | DROPEFFECT_MOVE;
+}
+
+void CCrystalEditView::
+OnDropSource (DROPEFFECT de)
+{
+  if (!IsDraggingText ())
+    return;
+
+  ASSERT_VALIDTEXTPOS (m_ptDraggedTextBegin);
+  ASSERT_VALIDTEXTPOS (m_ptDraggedTextEnd);
+
+  if (de == DROPEFFECT_MOVE)
+    {
+      m_pTextBuffer->DeleteText (this, m_ptDraggedTextBegin.y, m_ptDraggedTextBegin.x, m_ptDraggedTextEnd.y,
+                                 m_ptDraggedTextEnd.x, CE_ACTION_DRAGDROP);     // [JRT]
+
+    }
+}
+
+void CCrystalEditView::
+UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwFlags, int nLineIndex /*= -1*/ )
+{
+  CCrystalTextView::UpdateView (pSource, pContext, dwFlags, nLineIndex);
+
+  if (m_bSelectionPushed && pContext != NULL)
+    {
+      pContext->RecalcPoint (m_ptSavedSelStart);
+      pContext->RecalcPoint (m_ptSavedSelEnd);
+      ASSERT_VALIDTEXTPOS (m_ptSavedSelStart);
+      ASSERT_VALIDTEXTPOS (m_ptSavedSelEnd);
+    }
+}
+
+void CCrystalEditView::
+OnEditReplace ()
+{
+  if (!QueryEditable ())
+    return;
+
+  CWinApp *pApp = AfxGetApp ();
+  ASSERT (pApp != NULL);
+
+  CEditReplaceDlg dlg (this);
+
+  if (m_bLastReplace)
+    {
+      //  Get the latest Replace parameters
+      dlg.m_bMatchCase = (m_dwLastReplaceFlags & FIND_MATCH_CASE) != 0;
+      dlg.m_bWholeWord = (m_dwLastReplaceFlags & FIND_WHOLE_WORD) != 0;
+      dlg.m_bRegExp = (m_dwLastReplaceFlags & FIND_REGEXP) != 0;
+      if (m_pszLastFindWhat != NULL)
+        dlg.m_sText = m_pszLastFindWhat;
+    }
+  else
+    {
+      DWORD dwFlags;
+      if (!RegLoadNumber (HKEY_CURRENT_USER, REG_EDITPAD, _T ("ReplaceFlags"), &dwFlags))
+        dwFlags = 0;
+      dlg.m_bMatchCase = (dwFlags & FIND_MATCH_CASE) != 0;
+      dlg.m_bWholeWord = (dwFlags & FIND_WHOLE_WORD) != 0;
+      dlg.m_bRegExp = (dwFlags & FIND_REGEXP) != 0;
+      // dlg.m_sText = pApp->GetProfileString (REG_REPLACE_SUBKEY, REG_FIND_WHAT, _T (""));
+      // dlg.m_sNewText = pApp->GetProfileString (REG_REPLACE_SUBKEY, REG_REPLACE_WITH, _T (""));
+    }
+
+  if (IsSelection ())
+    {
+      GetSelection (m_ptSavedSelStart, m_ptSavedSelEnd);
+      m_bSelectionPushed = TRUE;
+
+      dlg.m_nScope = 0;         //  Replace in current selection
+
+      dlg.m_ptCurrentPos = m_ptSavedSelStart;
+      dlg.m_bEnableScopeSelection = TRUE;
+      dlg.m_ptBlockBegin = m_ptSavedSelStart;
+      dlg.m_ptBlockEnd = m_ptSavedSelEnd;
+    }
+  else
+    {
+      dlg.m_nScope = 1;         //  Replace in whole text
+
+      dlg.m_ptCurrentPos = GetCursorPos ();
+      dlg.m_bEnableScopeSelection = FALSE;
+
+      CPoint ptCursorPos = GetCursorPos (), ptStart = WordToLeft (ptCursorPos), ptEnd = WordToRight (ptCursorPos);
+      if (IsValidTextPos (ptStart) && IsValidTextPos (ptEnd) && ptStart != ptEnd)
+        GetText (ptStart, ptEnd, dlg.m_sText);
+    }
+
+  //  Execute Replace dialog
+  // m_bShowInactiveSelection = TRUE; // FP: removed because I like it
+  dlg.DoModal ();
+  // m_bShowInactiveSelection = FALSE; // FP: removed because I like it
+
+  //  Save Replace parameters for 'F3' command
+  m_bLastReplace = TRUE;
+  if (m_pszLastFindWhat != NULL)
+    free (m_pszLastFindWhat);
+  m_pszLastFindWhat = _tcsdup (dlg.m_sText);
+  m_dwLastReplaceFlags = 0;
+  if (dlg.m_bMatchCase)
+    m_dwLastReplaceFlags |= FIND_MATCH_CASE;
+  if (dlg.m_bWholeWord)
+    m_dwLastReplaceFlags |= FIND_WHOLE_WORD;
+  if (dlg.m_bRegExp)
+    m_dwLastReplaceFlags |= FIND_REGEXP;
+
+  //  Restore selection
+  if (m_bSelectionPushed)
+    {
+      SetSelection (m_ptSavedSelStart, m_ptSavedSelEnd);
+      m_bSelectionPushed = FALSE;
+    }
+
+  //  Save search parameters to registry
+  VERIFY (RegSaveNumber (HKEY_CURRENT_USER, REG_EDITPAD, _T ("ReplaceFlags"), m_dwLastReplaceFlags));
+  // pApp->WriteProfileString (REG_REPLACE_SUBKEY, REG_FIND_WHAT, dlg.m_sText);
+  // pApp->WriteProfileString (REG_REPLACE_SUBKEY, REG_REPLACE_WITH, dlg.m_sNewText);
+}
+
+BOOL CCrystalEditView::
+ReplaceSelection (LPCTSTR pszNewText, DWORD dwFlags)
+{
+  if (!pszNewText)
+    pszNewText = _T ("");
+  /*ASSERT (pszNewText != NULL);
+  if (!IsSelection ())
+    return FALSE;*/
+
+  CPoint ptCursorPos;
+  if (IsSelection ())
+    {
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+
+      ptCursorPos = ptSelStart;
+      /*SetAnchor (ptCursorPos);
+      SetSelection (ptCursorPos, ptCursorPos);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);*/
+
+      // [JRT]:
+      m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_REPLACE, FALSE);
+    }
+  else
+    ptCursorPos = GetCursorPos ();
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+
+  int x, y;
+  if (dwFlags & FIND_REGEXP)
+    {
+      LPTSTR lpszNewStr;
+      if (m_pszMatched && !RxReplace(pszNewText, m_pszMatched, m_nLastFindWhatLen, m_rxmatch, &lpszNewStr, &m_nLastReplaceLen))
+        {
+          CString text;
+          if (lpszNewStr && m_nLastReplaceLen > 0)
+            {
+              LPTSTR buf = text.GetBuffer (m_nLastReplaceLen + 1);
+              _tcsncpy (buf, lpszNewStr, m_nLastReplaceLen + 1);
+              buf [m_nLastReplaceLen] = _T('\0');
+              text.ReleaseBuffer ();
+            }
+          else
+            text.Empty ();
+          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, y, x, CE_ACTION_REPLACE, FALSE);  //  [JRT+FRD]
+          if (lpszNewStr)
+            free(lpszNewStr);
+        }
+    }
+  else
+    {
+      m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszNewText, y, x, CE_ACTION_REPLACE, FALSE);  //  [JRT]
+      m_nLastReplaceLen = _tcslen (pszNewText);
+    }
+  CPoint ptEndOfBlock = CPoint (x, y);
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+  ASSERT_VALIDTEXTPOS (ptEndOfBlock);
+  SetAnchor (ptEndOfBlock);
+  SetSelection (ptCursorPos, ptEndOfBlock);
+  SetCursorPos (ptEndOfBlock);
+  //EnsureVisible (ptEndOfBlock);
+  return TRUE;
+}
+
+void CCrystalEditView::
+OnUpdateEditUndo (CCmdUI * pCmdUI)
+{
+  BOOL bCanUndo = m_pTextBuffer != NULL && m_pTextBuffer->CanUndo ();
+  pCmdUI->Enable (bCanUndo);
+
+  //  Since we need text only for menus...
+  if (pCmdUI->m_pMenu != NULL)
+    {
+      //  Tune up 'resource handle'
+      HINSTANCE hOldResHandle = AfxGetResourceHandle ();
+      AfxSetResourceHandle (GetResourceHandle ());
+
+      CString menu;
+      if (bCanUndo)
+        {
+          //  Format menu item text using the provided item description
+          CString desc;
+          m_pTextBuffer->GetUndoDescription (desc);
+          menu.Format (IDS_MENU_UNDO_FORMAT, desc);
+        }
+      else
+        {
+          //  Just load default menu item text
+          menu.LoadString (IDS_MENU_UNDO_DEFAULT);
+        }
+
+      //  Restore original handle
+      AfxSetResourceHandle (hOldResHandle);
+
+      //  Set menu item text
+      pCmdUI->SetText (menu);
+    }
+}
+
+void CCrystalEditView::
+OnEditUndo ()
+{
+  if (m_pTextBuffer != NULL && m_pTextBuffer->CanUndo ())
+    {
+      CPoint ptCursorPos;
+      if (m_pTextBuffer->Undo (ptCursorPos))
+        {
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+        }
+    }
+}
+
+//  [JRT]
+void CCrystalEditView::
+SetDisableBSAtSOL (BOOL bDisableBSAtSOL)
+{
+  m_bDisableBSAtSOL = bDisableBSAtSOL;
+}
+
+void CCrystalEditView::
+OnEditRedo ()
+{
+  if (m_pTextBuffer != NULL && m_pTextBuffer->CanRedo ())
+    {
+      CPoint ptCursorPos;
+      if (m_pTextBuffer->Redo (ptCursorPos))
+        {
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+        }
+    }
+}
+
+void CCrystalEditView::
+OnUpdateEditRedo (CCmdUI * pCmdUI)
+{
+  BOOL bCanRedo = m_pTextBuffer != NULL && m_pTextBuffer->CanRedo ();
+  pCmdUI->Enable (bCanRedo);
+
+  //  Since we need text only for menus...
+  if (pCmdUI->m_pMenu != NULL)
+    {
+      //  Tune up 'resource handle'
+      HINSTANCE hOldResHandle = AfxGetResourceHandle ();
+      AfxSetResourceHandle (GetResourceHandle ());
+
+      CString menu;
+      if (bCanRedo)
+        {
+          //  Format menu item text using the provided item description
+          CString desc;
+          m_pTextBuffer->GetRedoDescription (desc);
+          menu.Format (IDS_MENU_REDO_FORMAT, desc);
+        }
+      else
+        {
+          //  Just load default menu item text
+          menu.LoadString (IDS_MENU_REDO_DEFAULT);
+        }
+
+      //  Restore original handle
+      AfxSetResourceHandle (hOldResHandle);
+
+      //  Set menu item text
+      pCmdUI->SetText (menu);
+    }
+}
+
+bool
+isopenbrace (TCHAR c)
+{
+  return c == _T ('{') || c == _T ('(') || c == _T ('[') || c == _T ('<');
+}
+
+bool
+isclosebrace (TCHAR c)
+{
+  return c == _T ('}') || c == _T ('}') || c == _T (']') || c == _T ('>');
+}
+
+bool
+isopenbrace (LPCTSTR s)
+{
+  return s[1] == _T ('\0') && isopenbrace (*s);
+}
+
+bool
+isclosebrace (LPCTSTR s)
+{
+  return s[1] == _T ('\0') && isclosebrace (*s);
+}
+
+int
+bracetype (TCHAR c)
+{
+  static LPCTSTR braces = _T("{}()[]<>");
+  LPCTSTR pos = _tcschr (braces, c);
+  return pos ? pos - braces + 1 : 0;
+}
+
+int
+bracetype (LPCTSTR s)
+{
+  if (s[1])
+    return 0;
+  return bracetype (*s);
+}
+
+void CCrystalEditView::
+OnEditOperation (int nAction, LPCTSTR pszText)
+{
+  if (m_bAutoIndent)
+    {
+      //  Analyse last action...
+      if (nAction == CE_ACTION_TYPING && _tcscmp (pszText, _T ("\r\n")) == 0 && !m_bOvrMode)
+        {
+          //  Enter stroke!
+          CPoint ptCursorPos = GetCursorPos ();
+          ASSERT (ptCursorPos.y > 0);
+
+          //  Take indentation from the previos line
+          int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y - 1);
+          LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y - 1);
+          int nPos = 0;
+          while (nPos < nLength && isspace (pszLineChars[nPos]))
+            nPos++;
+
+          if (nPos > 0)
+            {
+              if ((GetFlags () & SRCOPT_BRACEGNU) && isclosebrace (pszLineChars[nLength - 1]) && ptCursorPos.y > 0 && nPos && nPos == nLength - 1)
+                {
+                  if (pszLineChars[nPos - 1] == _T ('\t'))
+                    {
+                      nPos--;
+                    }
+                  else
+                    {
+                      int nTabSize = GetTabSize (),
+                        nDelta = nTabSize - nPos % nTabSize;
+                      if (!nDelta)
+                        {
+                          nDelta = nTabSize;
+                        }
+                      nPos -= nDelta;
+                      if (nPos < 0)
+                        {
+                          nPos = 0;
+                        }
+                    }
+                }
+              //  Insert part of the previos line
+              TCHAR *pszInsertStr;
+              if ((GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isopenbrace (pszLineChars[nLength - 1]))
+                {
+                  if (m_bInsertTabs)
+                    {
+                      pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nPos + 2));
+                      _tcsncpy (pszInsertStr, pszLineChars, nPos);
+                      pszInsertStr[nPos++] = _T ('\t');
+                    }
+                  else
+                    {
+                      int nTabSize = GetTabSize ();
+                      int nChars = nTabSize - nPos % nTabSize;
+                      pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nPos + nChars));
+                      _tcsncpy (pszInsertStr, pszLineChars, nPos);
+                      while (nChars--)
+                        {
+                          pszInsertStr[nPos++] = _T (' ');
+                        }
+                    }
+                }
+              else
+                {
+                  pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nPos + 1));
+                  _tcsncpy (pszInsertStr, pszLineChars, nPos);
+                }
+              pszInsertStr[nPos] = 0;
+
+              // m_pTextBuffer->BeginUndoGroup ();
+              int x, y;
+              m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x,
+                                         pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+              CPoint pt (x, y);
+              SetCursorPos (pt);
+              SetSelection (pt, pt);
+              SetAnchor (pt);
+              EnsureVisible (pt);
+              // m_pTextBuffer->FlushUndoGroup (this);
+            }
+          else
+            {
+              //  Insert part of the previos line
+              TCHAR *pszInsertStr;
+              if ((GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isopenbrace (pszLineChars[nLength - 1]))
+                {
+                  if (m_bInsertTabs)
+                    {
+                      pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
+                      pszInsertStr[nPos++] = _T ('\t');
+                    }
+                  else
+                    {
+                      int nTabSize = GetTabSize ();
+                      int nChars = nTabSize - nPos % nTabSize;
+                      pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nChars + 1));
+                      while (nChars--)
+                        {
+                          pszInsertStr[nPos++] = _T (' ');
+                        }
+                    }
+                  pszInsertStr[nPos] = 0;
+
+                  // m_pTextBuffer->BeginUndoGroup ();
+                  int x, y;
+                  m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x,
+                                             pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+                  CPoint pt (x, y);
+                  SetCursorPos (pt);
+                  SetSelection (pt, pt);
+                  SetAnchor (pt);
+                  EnsureVisible (pt);
+                  // m_pTextBuffer->FlushUndoGroup (this);
+                }
+            }
+        }
+      else if (nAction == CE_ACTION_TYPING && (GetFlags () & SRCOPT_FNBRACE) && bracetype (pszText) == 3)
+        {
+          //  Enter stroke!
+          CPoint ptCursorPos = GetCursorPos ();
+          LPCTSTR pszChars = m_pTextBuffer->GetLineChars (ptCursorPos.y);
+          if (ptCursorPos.x > 1 && xisalnum (pszChars[ptCursorPos.x - 2]))
+            {
+              LPTSTR pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
+              *pszInsertStr = _T (' ');
+              pszInsertStr[1] = _T ('\0');
+              // m_pTextBuffer->BeginUndoGroup ();
+              int x, y;
+              m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x - 1,
+                                         pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+              ptCursorPos.x = x + 1;
+              ptCursorPos.y = y;
+              SetCursorPos (ptCursorPos);
+              SetSelection (ptCursorPos, ptCursorPos);
+              SetAnchor (ptCursorPos);
+              EnsureVisible (ptCursorPos);
+              // m_pTextBuffer->FlushUndoGroup (this);
+            }
+        }
+      else if (nAction == CE_ACTION_TYPING && (GetFlags () & SRCOPT_BRACEGNU) && isopenbrace (pszText))
+        {
+          //  Enter stroke!
+          CPoint ptCursorPos = GetCursorPos ();
+
+          //  Take indentation from the previos line
+          int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
+          LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y );
+          int nPos = 0;
+          while (nPos < nLength && isspace (pszLineChars[nPos]))
+            nPos++;
+          if (nPos == nLength - 1)
+            {
+              TCHAR *pszInsertStr;
+              if (m_bInsertTabs)
+                {
+                  pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
+                  *pszInsertStr = _T ('\t');
+                  nPos = 1;
+                }
+              else
+                {
+                  int nTabSize = GetTabSize ();
+                  int nChars = nTabSize - nPos % nTabSize;
+                  pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nChars + 1));
+                  nPos = 0;
+                  while (nChars--)
+                    {
+                      pszInsertStr[nPos++] = _T (' ');
+                    }
+                }
+              pszInsertStr[nPos] = 0;
+
+              // m_pTextBuffer->BeginUndoGroup ();
+              int x, y;
+              m_pTextBuffer->InsertText (NULL, ptCursorPos.y, ptCursorPos.x - 1,
+                                         pszInsertStr, y, x, CE_ACTION_AUTOINDENT);
+              CPoint pt (x + 1, y);
+              SetCursorPos (pt);
+              SetSelection (pt, pt);
+              SetAnchor (pt);
+              EnsureVisible (pt);
+              // m_pTextBuffer->FlushUndoGroup (this);
+            }
+        }
+      else if (nAction == CE_ACTION_TYPING && (GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isclosebrace (pszText))
+        {
+          //  Enter stroke!
+          CPoint ptCursorPos = GetCursorPos ();
+
+          //  Take indentation from the previos line
+          int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
+          LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y );
+          int nPos = 0;
+          while (nPos < nLength && isspace (pszLineChars[nPos]))
+            nPos++;
+          if (ptCursorPos.y > 0 && nPos && nPos == nLength - 1)
+            {
+              if (pszLineChars[nPos - 1] == _T ('\t'))
+                {
+                  nPos = 1;
+                }
+              else
+                {
+                  int nTabSize = GetTabSize ();
+                  nPos = nTabSize - (ptCursorPos.x - 1) % nTabSize;
+                  if (!nPos)
+                    {
+                      nPos = nTabSize;
+                    }
+                  if (nPos > nLength - 1)
+                    {
+                      nPos = nLength - 1;
+                    }
+                }
+              // m_pTextBuffer->BeginUndoGroup ();
+              m_pTextBuffer->DeleteText (NULL, ptCursorPos.y, ptCursorPos.x - nPos - 1,
+                ptCursorPos.y, ptCursorPos.x - 1, CE_ACTION_AUTOINDENT);
+              ptCursorPos.x -= nPos;
+              SetCursorPos (ptCursorPos);
+              SetSelection (ptCursorPos, ptCursorPos);
+              SetAnchor (ptCursorPos);
+              EnsureVisible (ptCursorPos);
+              // m_pTextBuffer->FlushUndoGroup (this);
+            }
+        }
+    }
+}
+
+void CCrystalEditView::
+OnEditAutoComplete ()
+{
+  CPoint ptCursorPos = GetCursorPos ();
+  int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
+  LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y), pszEnd = pszText + ptCursorPos.x;
+  if (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszEnd)) && xisalnum (pszEnd[-1]))
+    {
+      LPCTSTR pszBegin = pszEnd - 1;
+      while (pszBegin > pszText && xisalnum (*pszBegin))
+        pszBegin--;
+      if (!xisalnum (*pszBegin))
+        pszBegin++;
+      nLength = pszEnd - pszBegin;
+      CString sText;
+      LPTSTR pszBuffer = sText.GetBuffer (nLength + 2);
+      *pszBuffer = _T('<');
+      _tcsncpy (pszBuffer + 1, pszBegin, nLength);
+      pszBuffer[nLength + 1] = _T('\0');
+      sText.ReleaseBuffer ();
+      CPoint ptTextPos;
+      ptCursorPos.x -= nLength;
+      BOOL bFound = FindText (sText, ptCursorPos, FIND_MATCH_CASE|FIND_REGEXP|FIND_DIRECTION_UP, TRUE, &ptTextPos);
+      if (!bFound)
+        {
+          ptCursorPos.x += nLength;
+          bFound = FindText (sText, ptCursorPos, FIND_MATCH_CASE|FIND_REGEXP, TRUE, &ptTextPos);
+          ptCursorPos.x -= nLength;
+        }
+      if (bFound)
+        {
+          int nFound = m_pTextBuffer->GetLineLength (ptTextPos.y);
+          pszText = m_pTextBuffer->GetLineChars (ptTextPos.y) + ptTextPos.x + m_nLastFindWhatLen;
+          nFound -= ptTextPos.x + m_nLastFindWhatLen;
+          pszBuffer = sText.GetBuffer (nFound + 1);
+          while (nFound-- && xisalnum (*pszText))
+            *pszBuffer++ = *pszText++;
+          *pszBuffer = _T('\0');
+          sText.ReleaseBuffer ();
+          if (!sText.IsEmpty ())
+            {
+              m_pTextBuffer->BeginUndoGroup ();
+              int x, y;
+              m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x + nLength, sText, y, x, CE_ACTION_AUTOCOMPLETE);
+              ptCursorPos.x = x;
+              ptCursorPos.y = y;
+              SetCursorPos (ptCursorPos);
+              SetSelection (ptCursorPos, ptCursorPos);
+              SetAnchor (ptCursorPos);
+              EnsureVisible (ptCursorPos);
+              m_pTextBuffer->FlushUndoGroup (this);
+            }
+        }
+    }
+}
+
+void CCrystalEditView::
+OnUpdateEditAutoComplete (CCmdUI * pCmdUI)
+{
+  CPoint ptCursorPos = GetCursorPos ();
+  int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
+  LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y) + ptCursorPos.x;
+  pCmdUI->Enable (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszText)) && xisalnum (pszText[-1]));
+}
+
+void CCrystalEditView::
+OnEditAutoExpand ()
+{
+  CPoint ptCursorPos = GetCursorPos ();
+  int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
+  LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y), pszEnd = pszText + ptCursorPos.x;
+  if (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszEnd)) && xisalnum (pszEnd[-1]))
+    {
+      LPCTSTR pszBegin = pszEnd - 1;
+      while (pszBegin > pszText && xisalnum (*pszBegin))
+        pszBegin--;
+      if (!xisalnum (*pszBegin))
+        pszBegin++;
+      nLength = pszEnd - pszBegin;
+      CString sText, sExpand;
+      LPTSTR pszBuffer = sText.GetBuffer (nLength + 1);
+      _tcsncpy (pszBuffer, pszBegin, nLength);
+      pszBuffer[nLength] = _T('\0');
+      sText.ReleaseBuffer ();
+      CPoint ptTextPos;
+      ptCursorPos.x -= nLength;
+      BOOL bFound = m_mapExpand->Lookup (sText, sExpand);
+      if (bFound && !sExpand.IsEmpty ())
+        {
+          m_pTextBuffer->BeginUndoGroup ();
+          int x, y;
+          m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCursorPos.y, ptCursorPos.x + nLength, CE_ACTION_AUTOEXPAND);
+          LPTSTR pszExpand = sExpand.GetBuffer (sExpand.GetLength () + 1);
+          LPTSTR pszSlash = _tcschr (pszExpand, _T ('\\'));
+          if (!pszSlash)
+            {
+              m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, y, x, CE_ACTION_AUTOEXPAND);
+              ptCursorPos.x = x;
+              ptCursorPos.y = y;
+              ASSERT_VALIDTEXTPOS (ptCursorPos);
+              SetCursorPos (ptCursorPos);
+              SetSelection (ptCursorPos, ptCursorPos);
+              SetAnchor (ptCursorPos);
+            }
+          else
+            {
+              *pszSlash++ = _T ('\0');
+              for(;;)
+                {
+                  m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, y, x, CE_ACTION_AUTOEXPAND);
+                  ptCursorPos.x = x;
+                  ptCursorPos.y = y;
+                  ASSERT_VALIDTEXTPOS (ptCursorPos);
+                  SetCursorPos (ptCursorPos);
+                  SetSelection (ptCursorPos, ptCursorPos);
+                  SetAnchor (ptCursorPos);
+                  OnEditOperation (CE_ACTION_TYPING, pszExpand);
+                  ptCursorPos = GetCursorPos ();
+                  if (!pszSlash)
+                    break;
+                  switch (*pszSlash)
+                    {
+                      case _T ('n'):
+                        {
+                          const static TCHAR szText[3] = _T ("\r\n");
+                          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, y, x, CE_ACTION_AUTOEXPAND);  //  [JRT]
+                          ptCursorPos.x = x;
+                          ptCursorPos.y = y;
+                          ASSERT_VALIDTEXTPOS (ptCursorPos);
+                          SetSelection (ptCursorPos, ptCursorPos);
+                          SetAnchor (ptCursorPos);
+                          SetCursorPos (ptCursorPos);
+                          OnEditOperation (CE_ACTION_TYPING, szText);
+                        }
+                        break;
+                      case _T ('u'):
+                        MoveUp (FALSE);
+                        break;
+                      case _T ('d'):
+                        MoveDown (FALSE);
+                        break;
+                      case _T ('l'):
+                        MoveLeft (FALSE);
+                        break;
+                      case _T ('r'):
+                        MoveRight (FALSE);
+                        break;
+                      case _T ('h'):
+                        MoveHome (FALSE);
+                        break;
+                      case _T ('f'):
+                        MoveEnd (FALSE);
+                        break;
+                      case _T ('b'):
+                        {
+                          CPoint ptSelStart = ptCursorPos;
+                          bool bDeleted = false;
+                          if (!(ptCursorPos.x))         // If At Start Of Line
+
+                            {
+                              if (!m_bDisableBSAtSOL)   // If DBSASOL Is Disabled
+
+                                {
+                                  if (ptCursorPos.y > 0)    // If Previous Lines Available
+
+                                    {
+                                      ptCursorPos.y--;  // Decrement To Previous Line
+
+                                      ptCursorPos.x = GetLineLength (
+                                                        ptCursorPos.y);   // Set Cursor To End Of Previous Line
+
+                                      bDeleted = true;  // Set Deleted Flag
+
+                                    }
+                                }
+                            }
+                          else                          // If Caret Not At SOL
+
+                            {
+                              ptCursorPos.x--;          // Decrement Position
+
+                              bDeleted = true;          // Set Deleted Flag
+
+                            }
+                          ASSERT_VALIDTEXTPOS (ptCursorPos);
+                          SetAnchor (ptCursorPos);
+                          SetSelection (ptCursorPos, ptCursorPos);
+                          SetCursorPos (ptCursorPos);
+
+                          if (bDeleted)
+                              m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptSelStart.y, ptSelStart.x, CE_ACTION_AUTOEXPAND);  // [JRT]
+                        }
+                        break;
+                      case _T ('e'):
+                        {
+                          CPoint ptSelEnd = ptCursorPos;
+                          if (ptSelEnd.x == GetLineLength (ptSelEnd.y))
+                            {
+                              if (ptSelEnd.y == GetLineCount () - 1)
+                                break;
+                              ptSelEnd.y++;
+                              ptSelEnd.x = 0;
+                            }
+                          else
+                            ptSelEnd.x++;
+                          m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_AUTOEXPAND);   // [JRT]
+                        }
+                        break;
+                      case _T ('t'):
+                        {
+                          static TCHAR szText[32];
+                          if (m_bInsertTabs)
+                            {
+                              *szText = _T ('\t');
+                              szText[1] = _T ('\0');
+                            }
+                          else
+                            {
+                              int nTabSize = GetTabSize ();
+                              int nChars = nTabSize - ptCursorPos.x % nTabSize;
+                              memset(szText, _T(' '), nChars);
+                              szText[nChars] = _T ('\0');
+                            }
+                          m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, y, x, CE_ACTION_AUTOEXPAND);  //  [JRT]
+                          ptCursorPos.x = x;
+                          ptCursorPos.y = y;
+                          ASSERT_VALIDTEXTPOS (ptCursorPos);
+                          SetSelection (ptCursorPos, ptCursorPos);
+                          SetAnchor (ptCursorPos);
+                          SetCursorPos (ptCursorPos);
+                        }
+                    }
+                  ptCursorPos = GetCursorPos ();
+                  pszExpand = pszSlash + 1;
+                  pszSlash = _tcschr (pszExpand, _T ('\\'));
+                  if (pszSlash)
+                    *pszSlash++ = _T ('\0');
+                }
+            }
+          sExpand.ReleaseBuffer ();
+          EnsureVisible (ptCursorPos);
+          m_pTextBuffer->FlushUndoGroup (this);
+        }
+    }
+}
+
+void CCrystalEditView::
+OnUpdateEditAutoExpand (CCmdUI * pCmdUI)
+{
+  if (m_mapExpand->IsEmpty ())
+    pCmdUI->Enable (FALSE);
+  else
+    OnUpdateEditAutoComplete (pCmdUI);
+}
+
+void CCrystalEditView::
+OnUpdateEditLowerCase (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (IsSelection ());
+}
+
+void CCrystalEditView::
+OnEditLowerCase ()
+{
+  if (IsSelection ())
+    {
+      CPoint ptCursorPos = GetCursorPos ();
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      CString text;
+      GetText (ptSelStart, ptSelEnd, text);
+      text.MakeLower ();
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      if (IsSelection ())
+        {
+          CPoint ptSelStart, ptSelEnd;
+          GetSelection (ptSelStart, ptSelEnd);
+    
+          ptCursorPos = ptSelStart;
+          /*SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);*/
+    
+          // [JRT]:
+          m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_LOWERCASE);
+        }
+
+      int x, y;
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_LOWERCASE);
+
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      SetAnchor (ptCursorPos);
+      SetSelection (ptSelStart, ptSelEnd);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+void CCrystalEditView::
+OnUpdateEditUpperCase (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (IsSelection ());
+}
+
+void CCrystalEditView::
+OnEditUpperCase ()
+{
+  if (IsSelection ())
+    {
+      CPoint ptCursorPos = GetCursorPos ();
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      CString text;
+      GetText (ptSelStart, ptSelEnd, text);
+      text.MakeUpper ();
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      if (IsSelection ())
+        {
+          CPoint ptSelStart, ptSelEnd;
+          GetSelection (ptSelStart, ptSelEnd);
+    
+          ptCursorPos = ptSelStart;
+          /*SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);*/
+    
+          // [JRT]:
+          m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_UPPERCASE);
+        }
+
+      int x, y;
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_UPPERCASE);
+
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      SetAnchor (ptCursorPos);
+      SetSelection (ptSelStart, ptSelEnd);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+void CCrystalEditView::
+OnUpdateEditSwapCase (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (IsSelection ());
+}
+
+void CCrystalEditView::
+OnEditSwapCase ()
+{
+  if (IsSelection ())
+    {
+      CPoint ptCursorPos = GetCursorPos ();
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      CString text;
+      GetText (ptSelStart, ptSelEnd, text);
+      int nLen = text.GetLength ();
+      LPTSTR pszText = text.GetBuffer (nLen + 1);
+      while (*pszText)
+        *pszText++ = (TCHAR)(_istlower (*pszText) ? _totupper (*pszText) : _totlower (*pszText));
+      text.ReleaseBuffer ();
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      if (IsSelection ())
+        {
+          CPoint ptSelStart, ptSelEnd;
+          GetSelection (ptSelStart, ptSelEnd);
+    
+          ptCursorPos = ptSelStart;
+          /*SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);*/
+    
+          // [JRT]:
+          m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_SWAPCASE);
+        }
+
+      int x, y;
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_SWAPCASE);
+
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      SetAnchor (ptCursorPos);
+      SetSelection (ptSelStart, ptSelEnd);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+void CCrystalEditView::
+OnUpdateEditCapitalize (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (IsSelection ());
+}
+
+void CCrystalEditView::
+OnEditCapitalize ()
+{
+  if (IsSelection ())
+    {
+      CPoint ptCursorPos = GetCursorPos ();
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      CString text;
+      GetText (ptSelStart, ptSelEnd, text);
+      int nLen = text.GetLength ();
+      LPTSTR pszText = text.GetBuffer (nLen + 1);
+      bool bCapitalize = true;
+      while (*pszText)
+        {
+          if (_istspace (*pszText))
+            bCapitalize = true;
+          else if (_istalpha (*pszText))
+            if (bCapitalize)
+              {
+                *pszText = (TCHAR)_totupper (*pszText);
+                bCapitalize = false;
+              }
+            else
+              *pszText = (TCHAR)_totlower (*pszText);
+          pszText++;
+        }
+      text.ReleaseBuffer ();
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      if (IsSelection ())
+        {
+          CPoint ptSelStart, ptSelEnd;
+          GetSelection (ptSelStart, ptSelEnd);
+    
+          ptCursorPos = ptSelStart;
+          /*SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);*/
+    
+          // [JRT]:
+          m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_CAPITALIZE);
+        }
+
+      int x, y;
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_CAPITALIZE);
+
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      SetAnchor (ptCursorPos);
+      SetSelection (ptSelStart, ptSelEnd);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+void CCrystalEditView::
+OnUpdateEditSentence (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (IsSelection ());
+}
+
+void CCrystalEditView::
+OnEditSentence ()
+{
+  if (IsSelection ())
+    {
+      CPoint ptCursorPos = GetCursorPos ();
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      CString text;
+      GetText (ptSelStart, ptSelEnd, text);
+      int nLen = text.GetLength ();
+      LPTSTR pszText = text.GetBuffer (nLen + 1);
+      bool bCapitalize = true;
+      while (*pszText)
+        {
+          if (!_istspace (*pszText))
+            if (*pszText == _T ('.'))
+              {
+                if (pszText[1] && !_istdigit (pszText[1]))
+                  bCapitalize = true;
+              }
+            else if (_istalpha (*pszText))
+              if (bCapitalize)
+                {
+                  *pszText = (TCHAR)_totupper (*pszText);
+                  bCapitalize = false;
+                }
+              else
+                *pszText = (TCHAR)_totlower (*pszText);
+          pszText++;
+        }
+      text.ReleaseBuffer ();
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      if (IsSelection ())
+        {
+          CPoint ptSelStart, ptSelEnd;
+          GetSelection (ptSelStart, ptSelEnd);
+    
+          ptCursorPos = ptSelStart;
+          /*SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);*/
+    
+          // [JRT]:
+          m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_SENTENCIZE);
+        }
+
+      int x, y;
+      m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, y, x, CE_ACTION_SENTENCIZE);
+
+      ASSERT_VALIDTEXTPOS (ptCursorPos);
+      SetAnchor (ptCursorPos);
+      SetSelection (ptSelStart, ptSelEnd);
+      SetCursorPos (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+//BEGIN SW
+void CCrystalEditView::OnUpdateEditGotoLastChange( CCmdUI *pCmdUI )
+{
+       CPoint  ptLastChange = m_pTextBuffer->GetLastChangePos();
+       pCmdUI->Enable( ptLastChange.x > 0 && ptLastChange.y > -1 );
+}
+
+void CCrystalEditView::OnEditGotoLastChange()
+{
+       CPoint  ptLastChange = m_pTextBuffer->GetLastChangePos();
+       if( ptLastChange.x < 0 || ptLastChange.y < 0 )
+               return;
+
+       // goto last change
+       SetCursorPos( ptLastChange );
+       SetSelection( ptLastChange, ptLastChange );
+       EnsureVisible( ptLastChange );
+}
+//END SW
+
+int CCrystalEditView::SpellGetLine (struct SpellData_t *pdata)
+{
+  int nCount;
+  CCrystalEditView *pView = (CCrystalEditView*) pdata->pUserData;
+  static TCHAR szBuffer[4096];
+
+  if (pdata->nRow < pView->GetLineCount ())
+    {
+      nCount = pView->GetLineLength (pdata->nRow) + 1;
+      /*if (pdata->pszBuffer)
+        free (pdata->pszBuffer);
+      pdata->pszBuffer = (LPTSTR) malloc (nCount + 2);*/
+      pdata->pszBuffer = szBuffer;
+      *pdata->pszBuffer = _T ('^');
+      if (nCount > 1)
+        _tcscpy (pdata->pszBuffer + 1, pView->GetLineChars (pdata->nRow));
+      else
+        pdata->pszBuffer[nCount++] = _T (' ');
+      pdata->pszBuffer[nCount++] = _T ('\n');
+      pdata->pszBuffer[nCount] = _T ('\0');
+      pdata->nRow++;
+      return nCount;
+    }
+  pdata->pszBuffer = szBuffer;
+  *pdata->pszBuffer = _T ('\0');
+  return 0;
+}
+
+int CCrystalEditView::SpellNotify (int nEvent, struct SpellData_t *pdata)
+{
+  CCrystalEditView *pView = (CCrystalEditView*) pdata->pUserData;
+  CPoint ptStartPos, ptEndPos;
+  int x, y;
+
+  switch (nEvent)
+    {
+      case SN_FOUND:
+        ptStartPos.x = pdata->nColumn - 1;
+        ptStartPos.y = pdata->nRow - 1;
+        ptEndPos.x = pdata->nColumn - 1 + _tcslen (pdata->pszWord);
+        ptEndPos.y = pdata->nRow - 1;
+        if (!pView->IsValidTextPos (ptStartPos))
+          if (ptStartPos.x > 0)
+            ptStartPos.x--;
+          else
+            ptStartPos.x = 0;
+        if (!pView->IsValidTextPos (ptEndPos))
+          if (ptEndPos.x > 0)
+            ptEndPos.x--;
+          else
+            ptEndPos.x = 0;
+        pView->SetAnchor (ptStartPos);
+        pView->SetSelection (ptStartPos, ptEndPos);
+        pView->SetCursorPos (ptStartPos);
+        pView->EnsureVisible (ptStartPos);
+      break;
+      case SN_REPLACED:
+        if (pView->IsSelection ())
+          {
+            pView->GetSelection (ptStartPos, ptEndPos);
+            pView->m_pTextBuffer->DeleteText (pView, ptStartPos.y, ptStartPos.x, ptEndPos.y, ptEndPos.x, CE_ACTION_SPELL);
+            pView->m_pTextBuffer->InsertText (pView, ptStartPos.y, ptStartPos.x, pdata->pszWord, y, x, CE_ACTION_SPELL);
+            ptEndPos.x = x;
+            ptEndPos.y = y;
+            pView->SetAnchor (ptEndPos);
+            pView->SetSelection (ptEndPos, ptEndPos);
+            pView->SetCursorPos (ptEndPos);
+          }
+      break;
+      case SN_FINISHED:
+        ptStartPos = pView->GetCursorPos ();
+        pView->SetAnchor (ptStartPos);
+        pView->SetSelection (ptStartPos, ptStartPos);
+        pView->SetCursorPos (ptStartPos);
+        pView->EnsureVisible (ptStartPos);
+        ::MessageBox (pdata->hParent, _T ("Spellchecking finished."), _T ("WIspell"), MB_OK|MB_ICONINFORMATION);
+    }
+  return 0;
+}
+
+HMODULE CCrystalEditView::hSpellDll = NULL;
+TCHAR CCrystalEditView::szWIspellPath[_MAX_PATH];
+SpellData CCrystalEditView::spellData;
+int (*CCrystalEditView::SpellInit) (SpellData*);
+int (*CCrystalEditView::SpellCheck) (SpellData*);
+int (*CCrystalEditView::SpellConfig) (SpellData*);
+
+BOOL CCrystalEditView::LoadSpellDll (BOOL bAlert /*= TRUE*/)
+{
+  if (hSpellDll)
+    return TRUE;
+  CString sPath = szWIspellPath;
+  if (!sPath.IsEmpty () && sPath[sPath.GetLength () - 1] != _T('\\'))
+    sPath += _T ('\\');
+  sPath += _T ("wispell.dll");
+  hSpellDll = LoadLibrary (sPath);
+  if (hSpellDll)
+    {
+      SpellInit = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellInit");
+      SpellCheck = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellCheck");
+      SpellConfig = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellConfig");
+      if (SpellInit)
+        SpellInit (&spellData);
+      _tcscpy (spellData.szIspell, szWIspellPath);
+      spellData.GetLine = SpellGetLine;
+      spellData.Notify = SpellNotify;
+    }
+  else
+    {
+      SpellInit = SpellCheck = SpellConfig = NULL;
+      if (bAlert)
+        ::MessageBox (AfxGetMainWnd ()->GetSafeHwnd (), _T ("Error loading \"wispell.dll\"."), _T ("Error"), MB_OK|MB_ICONEXCLAMATION);
+    }
+  return hSpellDll != NULL;
+}
+
+void CCrystalEditView::
+OnUpdateToolsSpelling (CCmdUI * pCmdUI)
+{
+  CPoint ptCursorPos = GetCursorPos ();
+  int nLines = GetLineCount () - 1;
+  pCmdUI->Enable (LoadSpellDll (FALSE) && ptCursorPos.y < nLines);
+}
+
+void CCrystalEditView::
+OnToolsSpelling ()
+{
+  CPoint ptCursorPos = GetCursorPos ();
+  if (LoadSpellDll () && ptCursorPos.y < GetLineCount ())
+    {
+      spellData.hParent = GetSafeHwnd ();
+      spellData.nRow = ptCursorPos.y;
+      spellData.pUserData = (LPVOID) (LPCVOID) this;
+      spellData.pszBuffer = NULL;
+      m_pTextBuffer->BeginUndoGroup ();
+      if (SpellCheck (&spellData) == IDCANCEL)
+        {
+          m_pTextBuffer->FlushUndoGroup (this);
+          OnEditUndo ();
+        }
+      else
+        m_pTextBuffer->FlushUndoGroup (this);
+      /*if (spellData.pszBuffer)
+        free (spellData.pszBuffer);*/
+    }
+}
+
+void CCrystalEditView::
+OnUpdateToolsCharCoding (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (IsSelection ());
+}
+
+long str_pos (LPCTSTR whole, LPCTSTR piece);
+
+void CCrystalEditView::
+OnToolsCharCoding ()
+{
+  if (IsSelection ())
+    {
+      CWaitCursor wait;
+      CPoint ptCursorPos = GetCursorPos ();
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      CString sText;
+      GetText (ptSelStart, ptSelEnd, sText);
+      CCharConvDlg dlg;
+      dlg.m_sOriginal = sText;
+      LPTSTR pszEnd = dlg.m_sOriginal.GetBuffer (dlg.m_sOriginal.GetLength () + 1);
+      for (int i = 0; i < 13; i++)
+        {
+          pszEnd = _tcschr (pszEnd, _T ('\n'));
+          if (pszEnd)
+            pszEnd++;
+          else
+            break;
+        }
+      if (pszEnd)
+        *pszEnd = _T ('\0');
+      dlg.m_sOriginal.ReleaseBuffer ();
+      if (dlg.DoModal () != IDOK)
+        return;
+      LPTSTR pszNew;
+      if (!iconvert_new (sText, &pszNew, dlg.m_nSource, dlg.m_nDest, dlg.m_bAlpha != FALSE))
+        {
+          ASSERT (pszNew);
+          m_pTextBuffer->BeginUndoGroup ();
+
+          m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_RECODE);
+
+          int x, y;
+          m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, pszNew, y, x, CE_ACTION_RECODE);
+
+          if (IsValidTextPos (ptCursorPos))
+            ptCursorPos.x = 0;
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetSelection (ptSelStart, ptSelEnd);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+
+          m_pTextBuffer->FlushUndoGroup (this);
+        }
+      if (pszNew)
+        free (pszNew);
+    }
+}
+
+void CCrystalEditView::
+OnEditDeleteWord ()
+{
+  if (!IsSelection ())
+    MoveWordRight (TRUE);
+  if (IsSelection ())
+    {
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE);
+
+      ASSERT_VALIDTEXTPOS (ptSelStart);
+      SetAnchor (ptSelStart);
+      SetSelection (ptSelStart, ptSelStart);
+      SetCursorPos (ptSelStart);
+      EnsureVisible (ptSelStart);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+void CCrystalEditView::
+OnEditDeleteWordBack ()
+{
+  if (!IsSelection ())
+    MoveWordLeft (TRUE);
+  if (IsSelection ())
+    {
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+
+      m_pTextBuffer->BeginUndoGroup ();
+
+      m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE);
+
+      ASSERT_VALIDTEXTPOS (ptSelStart);
+      SetAnchor (ptSelStart);
+      SetSelection (ptSelStart, ptSelStart);
+      SetCursorPos (ptSelStart);
+      EnsureVisible (ptSelStart);
+
+      m_pTextBuffer->FlushUndoGroup (this);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////
+#pragma warning ( default : 4100 )
diff --git a/Src/editlib/ccrystaleditview.h b/Src/editlib/ccrystaleditview.h
new file mode 100644 (file)
index 0000000..5a89333
--- /dev/null
@@ -0,0 +1,194 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ccrystaleditview.h
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Interface of the CCrystalEditView class, a part of Crystal Edit - syntax
+//  coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CCRYSTALEDITVIEW_H__8F3F8B63_6F66_11D2_8C34_0080ADB86836__INCLUDED_)
+#define AFX_CCRYSTALEDITVIEW_H__8F3F8B63_6F66_11D2_8C34_0080ADB86836__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "ccrystaltextview.h"
+#include "wispelld.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//  Forward class declarations
+
+class CEditDropTargetImpl;
+
+/////////////////////////////////////////////////////////////////////////////
+//  CCrystalEditView view
+
+class EDITPADC_CLASS CCrystalEditView : public CCrystalTextView
+  {
+    DECLARE_DYNCREATE (CCrystalEditView)
+
+public :
+    int m_nLastReplaceLen;
+    CMap<CString, LPCTSTR, CString, LPCTSTR> *m_mapExpand;
+
+    static HMODULE hSpellDll;
+    static TCHAR szWIspellPath[_MAX_PATH];
+    static SpellData spellData;
+    static int (*SpellInit) (SpellData*);
+    static int (*SpellCheck) (SpellData*);
+    static int (*SpellConfig) (SpellData*);
+    static BOOL LoadSpellDll (BOOL bAlert = TRUE);
+    static int SpellGetLine (struct SpellData_t *pdata);
+    static int SpellNotify (int nEvent, struct SpellData_t *pdata);
+
+protected:
+    BOOL m_bLastReplace;
+    DWORD m_dwLastReplaceFlags;
+
+private :
+    BOOL m_bOvrMode;
+    BOOL m_bDropPosVisible;
+    CPoint m_ptSavedCaretPos;
+    CPoint m_ptDropPos;
+    BOOL m_bSelectionPushed;
+    CPoint m_ptSavedSelStart, m_ptSavedSelEnd;
+    BOOL m_bAutoIndent;
+    BOOL m_bInsertTabs;
+
+    //  [JRT]
+    BOOL m_bDisableBSAtSOL;       // Disable BS At Start Of Line
+
+
+public :
+    virtual void ResetView ();
+protected :
+    CEditDropTargetImpl * m_pDropTarget;
+    virtual DROPEFFECT GetDropEffect ();
+    virtual void OnDropSource (DROPEFFECT de);
+    void Paste ();
+    void Cut ();
+    BOOL DeleteCurrentSelection ();
+
+    // Attributes
+public :
+    BOOL GetAutoIndent () const;
+    void SetAutoIndent (BOOL bAutoIndent);
+    BOOL GetInsertTabs () const;
+    void SetInsertTabs (BOOL bInsertTabs);
+
+    //  [JRT]
+    void SetDisableBSAtSOL (BOOL bDisableBSAtSOL);
+    BOOL GetDisableBSAtSOL () const;
+
+    // Operations
+public :
+    CCrystalEditView ();
+    ~CCrystalEditView ();
+
+    BOOL GetOverwriteMode () const;
+    void SetOverwriteMode (BOOL bOvrMode = TRUE);
+
+    void ShowDropIndicator (const CPoint & point);
+    void HideDropIndicator ();
+
+    BOOL DoDropText (COleDataObject * pDataObject, const CPoint & ptClient);
+    void DoDragScroll (const CPoint & point);
+
+    virtual BOOL QueryEditable ();
+    virtual void UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwFlags, int nLineIndex = -1);
+
+    BOOL ReplaceSelection (LPCTSTR pszNewText, DWORD dwFlags);
+
+    virtual void OnEditOperation (int nAction, LPCTSTR pszText);
+
+    virtual bool DoSetTextType (TextDefinition *def);
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CCrystalEditView)
+    //}}AFX_VIRTUAL
+
+    // Implementation
+protected :
+
+    // Generated message map functions
+protected :
+    //{{AFX_MSG(CCrystalEditView)
+    afx_msg void OnEditPaste ();
+    afx_msg void OnUpdateEditCut (CCmdUI * pCmdUI);
+    afx_msg void OnEditCut ();
+    afx_msg void OnUpdateEditPaste (CCmdUI * pCmdUI);
+    afx_msg void OnEditDelete ();
+    afx_msg void OnChar (UINT nChar, UINT nRepCnt, UINT nFlags);
+    afx_msg void OnEditDeleteBack ();
+    afx_msg void OnEditUntab ();
+    afx_msg void OnEditTab ();
+    afx_msg void OnEditSwitchOvrmode ();
+    afx_msg void OnUpdateEditSwitchOvrmode (CCmdUI * pCmdUI);
+    afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct);
+    afx_msg void OnDestroy ();
+    afx_msg void OnEditReplace ();
+    afx_msg void OnUpdateEditUndo (CCmdUI * pCmdUI);
+    afx_msg void OnEditUndo ();
+    afx_msg void OnUpdateEditRedo (CCmdUI * pCmdUI);
+    afx_msg void OnEditRedo ();
+    afx_msg void OnUpdateEditAutoComplete (CCmdUI * pCmdUI);
+    afx_msg void OnEditAutoComplete ();
+    afx_msg void OnUpdateEditAutoExpand (CCmdUI * pCmdUI);
+    afx_msg void OnEditAutoExpand ();
+    afx_msg void OnUpdateEditLowerCase (CCmdUI * pCmdUI);
+    afx_msg void OnEditLowerCase ();
+    afx_msg void OnUpdateEditUpperCase (CCmdUI * pCmdUI);
+    afx_msg void OnEditUpperCase ();
+    afx_msg void OnUpdateEditSwapCase (CCmdUI * pCmdUI);
+    afx_msg void OnEditSwapCase ();
+    afx_msg void OnUpdateEditCapitalize (CCmdUI * pCmdUI);
+    afx_msg void OnEditCapitalize ();
+    afx_msg void OnUpdateEditSentence (CCmdUI * pCmdUI);
+    afx_msg void OnEditSentence ();
+    //}}AFX_MSG
+    afx_msg void OnUpdateIndicatorCol (CCmdUI * pCmdUI);
+    afx_msg void OnUpdateIndicatorOvr (CCmdUI * pCmdUI);
+    afx_msg void OnUpdateIndicatorRead (CCmdUI * pCmdUI);
+       //BEGIN SW
+       afx_msg void OnUpdateEditGotoLastChange(CCmdUI* pCmdUI);
+       afx_msg void OnEditGotoLastChange();
+       //END SW
+       afx_msg void OnUpdateToolsSpelling (CCmdUI * pCmdUI);
+       afx_msg void OnToolsSpelling ();
+       afx_msg void OnUpdateToolsCharCoding (CCmdUI * pCmdUI);
+       afx_msg void OnToolsCharCoding ();
+       afx_msg void OnEditDeleteWord ();
+       afx_msg void OnEditDeleteWordBack ();
+    DECLARE_MESSAGE_MAP ()
+  };
+
+/////////////////////////////////////////////////////////////////////////////
+
+#if ! (defined(CE_FROM_DLL) || defined(CE_DLL_BUILD))
+#include "ccrystaleditview.inl"
+#endif
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CCRYSTALEDITVIEW_H__8F3F8B63_6F66_11D2_8C34_0080ADB86836__INCLUDED_)
diff --git a/Src/editlib/ccrystaleditview.inl b/Src/editlib/ccrystaleditview.inl
new file mode 100644 (file)
index 0000000..f4528f2
--- /dev/null
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       CCrystalEditView.inl
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Inline functions of Crystal Edit classes
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __CCrystalEditView_INL_INCLUDED
+#define __CCrystalEditView_INL_INCLUDED
+
+#include "CCrystalEditView.h"
+
+inline BOOL CCrystalEditView::
+GetOverwriteMode ()
+const
+{
+  return m_bOvrMode;
+}
+
+inline void CCrystalEditView::SetOverwriteMode (BOOL bOvrMode /*= TRUE*/ )
+{
+  m_bOvrMode = bOvrMode;
+}
+
+inline BOOL CCrystalEditView::
+GetDisableBSAtSOL ()
+const
+{
+  return m_bDisableBSAtSOL;
+}
+
+inline BOOL CCrystalEditView::GetAutoIndent ()
+const
+{
+  return m_bAutoIndent;
+}
+
+inline void CCrystalEditView::SetAutoIndent (BOOL bAutoIndent)
+{
+  m_bAutoIndent = bAutoIndent;
+}
+
+inline BOOL CCrystalEditView::GetInsertTabs ()
+const
+{
+  return m_bInsertTabs;
+}
+
+inline void CCrystalEditView::SetInsertTabs (BOOL bInsertTabs)
+{
+  m_bInsertTabs = bInsertTabs;
+}
+
+#endif
diff --git a/Src/editlib/ccrystaltextbuffer.cpp b/Src/editlib/ccrystaltextbuffer.cpp
new file mode 100644 (file)
index 0000000..bd1e984
--- /dev/null
@@ -0,0 +1,1498 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ccrystaltextbuffer.cpp
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CCrystalTextBuffer class, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  17-Feb-99
+//  +   FIX: unnecessary 'HANDLE' in CCrystalTextBuffer::SaveToFile
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  21-Feb-99
+//      Paul Selormey, James R. Twine:
+//  +   FEATURE: description for Undo/Redo actions
+//  +   FEATURE: multiple MSVC-like bookmarks
+//  +   FEATURE: 'Disable backspace at beginning of line' option
+//  +   FEATURE: 'Disable drag-n-drop editing' option
+//
+//  +   FEATURE: changed layout of SUndoRecord. Now takes less memory
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: some other things I've forgotten ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//     ??-Aug-99
+//             Sven Wiegand (search for "//BEGIN SW" to find my changes):
+//     + FEATURE: Remembering the text-position of the latest change.
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//     24-Oct-99
+//             Sven Wiegand
+//     + FIX: Setting m_ptLastChange to the beginning of the selection in
+//                  InternalDeleteText(), so that position is valid in any case.
+//                  Editor won't crash any more i.e. by selecting whole buffer and
+//                  deleting it and then executing ID_EDIT_GOTO_LAST_CHANGE-command.
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include <malloc.h>
+#include "editcmd.h"
+#include "ccrystaltextbuffer.h"
+#include "ccrystaltextview.h"
+#include "filesup.h"
+#include "cs2cs.h"
+#include <mbctype.h> 
+
+#ifndef __AFXPRIV_H__
+#pragma message("Include <afxpriv.h> in your stdafx.h to avoid this message")
+#include <afxpriv.h>
+#endif
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  Line allocation granularity
+#define     CHAR_ALIGN                  16
+#define     ALIGN_BUF_SIZE(size)        ((size) / CHAR_ALIGN) * CHAR_ALIGN + CHAR_ALIGN;
+
+#define     UNDO_BUF_SIZE               1024
+
+const TCHAR crlf[] = _T ("\r\n");
+
+#ifdef _DEBUG
+#define _ADVANCED_BUGCHECK  1
+#endif
+
+int CCrystalTextBuffer::m_nDefaultEncoding = -1;
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextBuffer::SUndoRecord
+
+void CCrystalTextBuffer::SUndoRecord::
+SetText (LPCTSTR pszText)
+{
+  m_pszText = NULL;
+  if (pszText != NULL && pszText[0] != _T ('\0'))
+    {
+      int nLength = _tcslen (pszText);
+      if (nLength > 1)
+        {
+          m_pszText = new TCHAR[(nLength + 1) * sizeof (TCHAR)];
+          _tcscpy (m_pszText, pszText);
+        }
+      else
+        {
+          m_szText[0] = pszText[0];
+        }
+    }
+}
+
+void CCrystalTextBuffer::SUndoRecord::
+FreeText ()
+{
+  if (HIWORD ((DWORD) m_pszText) != 0)
+    delete m_pszText;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextBuffer::CUpdateContext
+
+void CCrystalTextBuffer::CInsertContext::
+RecalcPoint (CPoint & ptPoint)
+{
+  ASSERT (m_ptEnd.y > m_ptStart.y ||
+          m_ptEnd.y == m_ptStart.y && m_ptEnd.x >= m_ptStart.x);
+  if (ptPoint.y < m_ptStart.y)
+    return;
+  if (ptPoint.y > m_ptStart.y)
+    {
+      ptPoint.y += (m_ptEnd.y - m_ptStart.y);
+      return;
+    }
+  if (ptPoint.x <= m_ptStart.x)
+    return;
+  ptPoint.y += (m_ptEnd.y - m_ptStart.y);
+  ptPoint.x = m_ptEnd.x + (ptPoint.x - m_ptStart.x);
+}
+
+void CCrystalTextBuffer::CDeleteContext::
+RecalcPoint (CPoint & ptPoint)
+{
+  ASSERT (m_ptEnd.y > m_ptStart.y ||
+          m_ptEnd.y == m_ptStart.y && m_ptEnd.x >= m_ptStart.x);
+  if (ptPoint.y < m_ptStart.y)
+    return;
+  if (ptPoint.y > m_ptEnd.y)
+    {
+      ptPoint.y -= (m_ptEnd.y - m_ptStart.y);
+      return;
+    }
+  if (ptPoint.y == m_ptEnd.y && ptPoint.x >= m_ptEnd.x)
+    {
+      ptPoint.y = m_ptStart.y;
+      ptPoint.x = m_ptStart.x + (ptPoint.x - m_ptEnd.x);
+      return;
+    }
+  if (ptPoint.y == m_ptStart.y)
+    {
+      if (ptPoint.x > m_ptStart.x)
+        ptPoint.x = m_ptStart.x;
+      return;
+    }
+  ptPoint = m_ptStart;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextBuffer
+
+IMPLEMENT_DYNCREATE (CCrystalTextBuffer, CCmdTarget)
+
+CCrystalTextBuffer::CCrystalTextBuffer ()
+{
+  m_bInit = FALSE;
+  m_bReadOnly = FALSE;
+  m_bModified = FALSE;
+  m_bCreateBackupFile = FALSE;
+  m_nUndoPosition = 0;
+       //BEGIN SW
+       m_ptLastChange.x = m_ptLastChange.y = -1;
+       //END SW
+  m_nSourceEncoding = m_nDefaultEncoding;
+}
+
+CCrystalTextBuffer:: ~ CCrystalTextBuffer ()
+{
+  ASSERT (!m_bInit);            //  You must call FreeAll() before deleting the object
+}
+
+
+BEGIN_MESSAGE_MAP (CCrystalTextBuffer, CCmdTarget)
+//{{AFX_MSG_MAP(CCrystalTextBuffer)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextBuffer message handlers
+
+void CCrystalTextBuffer::InsertLine (LPCTSTR pszLine, int nLength /*= -1*/ , int nPosition /*= -1*/ )
+{
+  if (nLength == -1)
+    {
+      if (pszLine == NULL)
+        nLength = 0;
+      else
+        nLength = _tcslen (pszLine);
+    }
+
+  SLineInfo li;
+  li.m_nLength = nLength;
+  li.m_nMax = ALIGN_BUF_SIZE (li.m_nLength);
+  ASSERT (li.m_nMax >= li.m_nLength);
+  if (li.m_nMax > 0)
+    li.m_pcLine = new TCHAR[li.m_nMax];
+  if (li.m_nLength > 0)
+    memcpy (li.m_pcLine, pszLine, sizeof (TCHAR) * li.m_nLength);
+
+  if (nPosition == -1)
+    m_aLines.Add (li);
+  else
+    m_aLines.InsertAt (nPosition, li);
+
+#ifdef _DEBUG
+  int nLines = m_aLines.GetSize ();
+  if (nLines % 5000 == 0)
+    TRACE1 ("%d lines loaded!\n", nLines);
+#endif
+}
+
+void CCrystalTextBuffer::
+AppendLine (int nLineIndex, LPCTSTR pszChars, int nLength /*= -1*/ )
+{
+  if (nLength == -1)
+    {
+      if (pszChars == NULL)
+        return;
+      nLength = _tcslen (pszChars);
+    }
+
+  if (nLength == 0)
+    return;
+
+  register SLineInfo & li = m_aLines[nLineIndex];
+  int nBufNeeded = li.m_nLength + nLength;
+  if (nBufNeeded > li.m_nMax)
+    {
+      li.m_nMax = ALIGN_BUF_SIZE (nBufNeeded);
+      ASSERT (li.m_nMax >= li.m_nLength + nLength);
+      TCHAR *pcNewBuf = new TCHAR[li.m_nMax];
+      if (li.m_nLength > 0)
+        memcpy (pcNewBuf, li.m_pcLine, sizeof (TCHAR) * li.m_nLength);
+      delete li.m_pcLine;
+      li.m_pcLine = pcNewBuf;
+    }
+  memcpy (li.m_pcLine + li.m_nLength, pszChars, sizeof (TCHAR) * nLength);
+  li.m_nLength += nLength;
+  ASSERT (li.m_nLength <= li.m_nMax);
+}
+
+void CCrystalTextBuffer::
+FreeAll ()
+{
+  //  Free text
+  int nCount = m_aLines.GetSize ();
+  for (int I = 0; I < nCount; I++)
+    {
+      if (m_aLines[I].m_nMax > 0)
+        delete m_aLines[I].m_pcLine;
+    }
+  m_aLines.RemoveAll ();
+
+  //  Free undo buffer
+  int nBufSize = m_aUndoBuf.GetSize ();
+  for (I = 0; I < nBufSize; I++)
+    m_aUndoBuf[I].FreeText ();
+  m_aUndoBuf.RemoveAll ();
+
+  m_bInit = FALSE;
+       //BEGIN SW
+       m_ptLastChange.x = m_ptLastChange.y = -1;
+       //END SW
+}
+
+BOOL CCrystalTextBuffer::
+InitNew (int nCrlfStyle /*= CRLF_STYLE_DOS*/ )
+{
+  ASSERT (!m_bInit);
+  ASSERT (m_aLines.GetSize () == 0);
+  ASSERT (nCrlfStyle >= 0 && nCrlfStyle <= 2);
+  InsertLine (_T (""));
+  m_bInit = TRUE;
+  m_bReadOnly = FALSE;
+  m_nCRLFMode = nCrlfStyle;
+  m_bModified = FALSE;
+  m_nSyncPosition = m_nUndoPosition = 0;
+  m_bUndoGroup = m_bUndoBeginGroup = FALSE;
+  m_nUndoBufSize = UNDO_BUF_SIZE;
+  ASSERT (m_aUndoBuf.GetSize () == 0);
+  UpdateViews (NULL, NULL, UPDATE_RESET);
+       //BEGIN SW
+       m_ptLastChange.x = m_ptLastChange.y = -1;
+       //END SW
+  return TRUE;
+}
+
+BOOL CCrystalTextBuffer::
+GetReadOnly ()
+const
+{
+  ASSERT (m_bInit);        //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  return m_bReadOnly;
+}
+
+void CCrystalTextBuffer::SetReadOnly (BOOL bReadOnly /*= TRUE*/ )
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  m_bReadOnly = bReadOnly;
+}
+
+static LPCTSTR crlfs[] =
+  {
+    _T ("\x0d\x0a"), //  DOS/Windows style
+    _T ("\x0a"),     //  UNIX style
+    _T ("\x0a")      //  Macintosh style
+  };
+
+BOOL CCrystalTextBuffer::
+LoadFromFile (LPCTSTR pszFileName, int nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/ )
+{
+       ASSERT (!m_bInit);
+       ASSERT (m_aLines.GetSize () == 0);
+       
+       HANDLE hFile = NULL;
+       int nCurrentMax = 256;
+       LPTSTR pcLineBuf = new TCHAR[nCurrentMax];
+       
+       BOOL bSuccess = FALSE;
+       
+       int nExt = GetExtPosition (pszFileName);
+       if (pszFileName[nExt] == _T ('.'))
+               nExt++;
+       CCrystalTextView::TextDefinition *def = CCrystalTextView::GetTextType (pszFileName + nExt);
+       if (def && def->encoding != -1)
+               m_nSourceEncoding = def->encoding;
+       
+       __try
+       {
+               DWORD dwFileAttributes =::GetFileAttributes (pszFileName);
+               if (dwFileAttributes == (DWORD) - 1)
+                       __leave;
+               
+               hFile =::CreateFile (pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+               if (hFile == INVALID_HANDLE_VALUE)
+                       __leave;
+               
+        int nCurrentLength = 0;
+               
+        const DWORD dwBufSize = 32768;
+        LPTSTR pcBuf = (LPTSTR) _alloca (dwBufSize);
+        DWORD dwCurSize;
+        if (!::ReadFile (hFile, pcBuf, dwBufSize, &dwCurSize, NULL))
+                       __leave;
+               
+               if (nCrlfStyle == CRLF_STYLE_AUTOMATIC)
+               {
+                       //  Try to determine current CRLF mode
+                       for (DWORD I = 0; I < dwCurSize; I++)
+                       {
+                               if ((pcBuf[I] == _T('\x0d')) || (pcBuf[I] == _T('\x0a')))
+                    break;
+                       }
+                       if (I == dwCurSize)
+                       {
+                               //  By default (or in the case of empty file), set DOS style
+                               nCrlfStyle = CRLF_STYLE_DOS;
+                       }
+                       else
+                       {
+                               //  Otherwise, analyse the first occurance of line-feed character
+                               if (pcBuf[I] == _T('\x0a'))
+                               {
+                                       nCrlfStyle = CRLF_STYLE_UNIX;
+                               }
+                               else
+                               {
+                                       if (I < dwCurSize - 1 && pcBuf[I + 1] == _T ('\x0a'))
+                        nCrlfStyle = CRLF_STYLE_DOS;
+                                       else
+                        nCrlfStyle = CRLF_STYLE_MAC;
+                               }
+                       }
+               }
+               
+               ASSERT (nCrlfStyle >= 0 && nCrlfStyle <= 2);
+               m_nCRLFMode = nCrlfStyle;
+               LPCTSTR crlf = crlfs[nCrlfStyle];
+               
+               m_aLines.SetSize (0, 4096);
+               
+               DWORD dwBufPtr = 0;
+               int nCrlfPtr = 0;
+               while (dwBufPtr < dwCurSize)
+               {
+                       int c = pcBuf[dwBufPtr];
+                       dwBufPtr++;
+                       if (dwBufPtr == dwCurSize && dwCurSize == dwBufSize)
+                       {
+                               if (!::ReadFile (hFile, pcBuf, dwBufSize, &dwCurSize, NULL))
+                                       __leave;
+                               dwBufPtr = 0;
+                       }
+                       
+                       pcLineBuf[nCurrentLength] = (TCHAR) c;
+                       nCurrentLength++;
+                       if (nCurrentLength == nCurrentMax)
+                       {
+                               //  Reallocate line buffer
+                               nCurrentMax += 256;
+                               LPTSTR pcNewBuf = new TCHAR[nCurrentMax];
+                               memcpy (pcNewBuf, pcLineBuf, nCurrentLength);
+                               delete pcLineBuf;
+                               pcLineBuf = pcNewBuf;
+                       }
+                       
+                       if ((TCHAR) c == crlf[nCrlfPtr])
+                       {
+                               nCrlfPtr++;
+                               if (crlf[nCrlfPtr] == 0)
+                               {
+                                       pcLineBuf[nCurrentLength - nCrlfPtr] = 0;
+                                       if (m_nSourceEncoding >= 0)
+                                               iconvert (pcLineBuf, m_nSourceEncoding, 1, m_nSourceEncoding == 15);
+                                       InsertLine (pcLineBuf);
+                                       nCurrentLength = 0;
+                                       nCrlfPtr = 0;
+                               }
+                       }
+                       else
+                               nCrlfPtr = 0;
+               }
+               
+               pcLineBuf[nCurrentLength] = 0;
+               InsertLine (pcLineBuf);
+               
+               ASSERT (m_aLines.GetSize () > 0);   //  At least one empty line must present
+               
+               m_bInit = TRUE;
+               m_bReadOnly = (dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0;
+               m_bModified = FALSE;
+               m_bUndoGroup = m_bUndoBeginGroup = FALSE;
+               m_nUndoBufSize = UNDO_BUF_SIZE;
+               m_nSyncPosition = m_nUndoPosition = 0;
+               ASSERT (m_aUndoBuf.GetSize () == 0);
+               bSuccess = TRUE;
+               
+               RetypeViews (pszFileName);
+               UpdateViews (NULL, NULL, UPDATE_RESET);
+  }
+  __finally
+  {
+         if (pcLineBuf != NULL)
+                 delete pcLineBuf;
+  }
+  if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
+         ::CloseHandle (hFile);
+  //BEGIN SW
+  m_ptLastChange.x = m_ptLastChange.y = -1;
+  //END SW
+  return bSuccess;
+}
+
+BOOL CCrystalTextBuffer::
+SaveToFile (LPCTSTR pszFileName, int nCrlfStyle /*= CRLF_STYLE_AUTOMATIC*/ , BOOL bClearModifiedFlag /*= TRUE*/ )
+{
+  ASSERT (nCrlfStyle == CRLF_STYLE_AUTOMATIC || nCrlfStyle == CRLF_STYLE_DOS ||
+          nCrlfStyle == CRLF_STYLE_UNIX || nCrlfStyle == CRLF_STYLE_MAC);
+  ASSERT (m_bInit);
+  HANDLE hTempFile = INVALID_HANDLE_VALUE;
+  HANDLE hSearch = INVALID_HANDLE_VALUE;
+  TCHAR szTempFileDir[_MAX_PATH + 1];
+  TCHAR szTempFileName[_MAX_PATH + 1];
+  TCHAR szBackupFileName[_MAX_PATH + 1];
+  BOOL bSuccess = FALSE;
+  __try
+  {
+    TCHAR drive[_MAX_PATH], dir[_MAX_PATH], name[_MAX_PATH], ext[_MAX_PATH];
+#ifdef _UNICODE
+    _wsplitpath (pszFileName, drive, dir, name, ext);
+#else
+    _splitpath (pszFileName, drive, dir, name, ext);
+#endif
+    _tcscpy (szTempFileDir, drive);
+    _tcscat (szTempFileDir, dir);
+    _tcscpy (szBackupFileName, pszFileName);
+    _tcscat (szBackupFileName, _T (".bak"));
+
+    if (::GetTempFileName (szTempFileDir, _T ("CRE"), 0, szTempFileName) == 0)
+      __leave;
+
+      hTempFile =::CreateFile (szTempFileName, GENERIC_WRITE, 0, NULL,
+                               CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+      if (hTempFile == INVALID_HANDLE_VALUE)
+        __leave;
+
+        if (nCrlfStyle == CRLF_STYLE_AUTOMATIC)
+          nCrlfStyle = m_nCRLFMode;
+
+          ASSERT (nCrlfStyle >= 0 && nCrlfStyle <= 2);
+          LPCTSTR pszCRLF = crlfs[nCrlfStyle];
+          int nCRLFLength = _tcslen (pszCRLF);
+
+          int nLineCount = m_aLines.GetSize ();
+          for (int nLine = 0; nLine < nLineCount; nLine++)
+            {
+              int nLength = m_aLines[nLine].m_nLength;
+              DWORD dwWrittenBytes;
+              if (nLength > 0)
+                {
+                  LPCTSTR pszLine = m_aLines[nLine].m_pcLine;
+                  if (m_nSourceEncoding >= 0)
+                    {
+                      LPTSTR pszBuf;
+                      iconvert_new (m_aLines[nLine].m_pcLine, &pszBuf, 1, m_nSourceEncoding, m_nSourceEncoding == 15);
+                      if (!::WriteFile (hTempFile, pszBuf, nLength, &dwWrittenBytes, NULL))
+                        {
+                          free (pszBuf);
+                          __leave;
+                        }
+                      free (pszBuf);
+                    }
+                  else
+                    if (!::WriteFile (hTempFile, pszLine, nLength, &dwWrittenBytes, NULL))
+                      __leave;
+                  if (nLength != (int) dwWrittenBytes)
+                    __leave;
+                }
+              if (nLine < nLineCount - 1)     //  Last line must not end with CRLF
+
+                {
+                  if (!::WriteFile (hTempFile, pszCRLF, nCRLFLength, &dwWrittenBytes, NULL))
+                    __leave;
+                  if (nCRLFLength != (int) dwWrittenBytes)
+                    __leave;
+                }
+            }
+    ::CloseHandle (hTempFile);
+    hTempFile = INVALID_HANDLE_VALUE;
+
+    if (m_bCreateBackupFile)
+      {
+        WIN32_FIND_DATA wfd;
+        hSearch =::FindFirstFile (pszFileName, &wfd);
+        if (hSearch != INVALID_HANDLE_VALUE)
+          {
+            //  File exist - create backup file
+            ::DeleteFile (szBackupFileName);
+            if (!::MoveFile (pszFileName, szBackupFileName))
+              __leave;
+            ::FindClose (hSearch);
+            hSearch = INVALID_HANDLE_VALUE;
+          }
+      }
+    else
+      {
+        ::DeleteFile (pszFileName);
+      }
+
+    //  Move temporary file to target name
+    if (!::MoveFile (szTempFileName, pszFileName))
+      __leave;
+
+      if (bClearModifiedFlag)
+        {
+          SetModified (FALSE);
+          m_nSyncPosition = m_nUndoPosition;
+        }
+    bSuccess = TRUE;
+  }
+  __finally
+  {
+    if (hSearch != INVALID_HANDLE_VALUE)
+      ::FindClose (hSearch);
+      if (hTempFile != INVALID_HANDLE_VALUE)
+        ::CloseHandle (hTempFile);
+        ::DeleteFile (szTempFileName);
+      }
+      return bSuccess;
+}
+
+int CCrystalTextBuffer::
+GetCRLFMode ()
+{
+  return m_nCRLFMode;
+}
+
+void CCrystalTextBuffer::
+SetCRLFMode (int nCRLFMode)
+{
+  /*ASSERT (nCRLFMode == CRLF_STYLE_DOS ||
+          nCRLFMode == CRLF_STYLE_UNIX ||
+          nCRLFMode == CRLF_STYLE_MAC);*/
+  if (nCRLFMode >= 0)
+    {
+      m_nCRLFMode = nCRLFMode;
+    }
+}
+
+int CCrystalTextBuffer::
+GetLineCount ()
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  return m_aLines.GetSize ();
+}
+
+int CCrystalTextBuffer::
+GetLineLength (int nLine)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  return m_aLines[nLine].m_nLength;
+}
+
+LPTSTR CCrystalTextBuffer::
+GetLineChars (int nLine)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  return m_aLines[nLine].m_pcLine;
+}
+
+DWORD CCrystalTextBuffer::
+GetLineFlags (int nLine)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  return m_aLines[nLine].m_dwFlags;
+}
+
+static int
+FlagToIndex (DWORD dwFlag)
+{
+  int nIndex = 0;
+  while ((dwFlag & 1) == 0)
+    {
+      dwFlag = dwFlag >> 1;
+      nIndex++;
+      if (nIndex == 32)
+        return -1;
+    }
+  dwFlag = dwFlag & 0xFFFFFFFE;
+  if (dwFlag != 0)
+    return -1;
+  return nIndex;
+
+}
+
+int CCrystalTextBuffer::
+FindLineWithFlag (DWORD dwFlag)
+{
+  int nSize = m_aLines.GetSize ();
+  for (int L = 0; L < nSize; L++)
+    {
+      if ((m_aLines[L].m_dwFlags & dwFlag) != 0)
+        return L;
+    }
+  return -1;
+}
+
+int CCrystalTextBuffer::
+GetLineWithFlag (DWORD dwFlag)
+{
+  int nFlagIndex =::FlagToIndex (dwFlag);
+  if (nFlagIndex < 0)
+    {
+      ASSERT (FALSE);           //  Invalid flag passed in
+
+      return -1;
+    }
+  return FindLineWithFlag (dwFlag);
+}
+
+void CCrystalTextBuffer::
+SetLineFlag (int nLine, DWORD dwFlag, BOOL bSet, BOOL bRemoveFromPreviousLine /*= TRUE*/ , BOOL bUpdate /*=TRUE*/)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  int nFlagIndex =::FlagToIndex (dwFlag);
+  if (nFlagIndex < 0 && (nLine == -1 || bRemoveFromPreviousLine))
+    {
+      ASSERT (FALSE);           //  Invalid flag passed in
+
+      return;
+    }
+
+  if (nLine == -1)
+    {
+      ASSERT (!bSet);
+      nLine = FindLineWithFlag (dwFlag);
+      if (nLine == -1)
+        return;
+      bRemoveFromPreviousLine = FALSE;
+    }
+
+  DWORD dwNewFlags = m_aLines[nLine].m_dwFlags;
+  if (bSet)
+  {
+         if (dwFlag==0)
+                 dwNewFlags=0;
+         else
+               dwNewFlags = dwNewFlags | dwFlag;
+  }
+  else
+    dwNewFlags = dwNewFlags & ~dwFlag;
+
+  if (m_aLines[nLine].m_dwFlags != dwNewFlags)
+    {
+      if (bRemoveFromPreviousLine)
+        {
+          int nPrevLine = FindLineWithFlag (dwFlag);
+          if (bSet)
+            {
+              if (nPrevLine >= 0)
+                {
+                  ASSERT ((m_aLines[nPrevLine].m_dwFlags & dwFlag) != 0);
+                  m_aLines[nPrevLine].m_dwFlags &= ~dwFlag;
+                                 if (bUpdate)
+                                       UpdateViews (NULL, NULL, UPDATE_SINGLELINE | UPDATE_FLAGSONLY, nPrevLine);
+                }
+            }
+          else
+            {
+              ASSERT (nPrevLine == nLine);
+            }
+        }
+
+      m_aLines[nLine].m_dwFlags = dwNewFlags;
+      if (bUpdate)
+                 UpdateViews (NULL, NULL, UPDATE_SINGLELINE | UPDATE_FLAGSONLY, nLine);
+    }
+}
+
+void CCrystalTextBuffer::
+GetText (int nStartLine, int nStartChar, int nEndLine, int nEndChar, CString & text, LPCTSTR pszCRLF /*= NULL*/ )
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  ASSERT (nStartLine >= 0 && nStartLine < m_aLines.GetSize ());
+  ASSERT (nStartChar >= 0 && nStartChar <= m_aLines[nStartLine].m_nLength);
+  ASSERT (nEndLine >= 0 && nEndLine < m_aLines.GetSize ());
+  ASSERT (nEndChar >= 0 && nEndChar <= m_aLines[nEndLine].m_nLength);
+  ASSERT (nStartLine < nEndLine || nStartLine == nEndLine && nStartChar < nEndChar);
+
+  if (pszCRLF == NULL)
+    pszCRLF = crlf;
+  int nCRLFLength = _tcslen (pszCRLF);
+  ASSERT (nCRLFLength > 0);
+
+  int nBufSize = 0;
+  for (int L = nStartLine; L <= nEndLine; L++)
+    {
+      nBufSize += m_aLines[L].m_nLength;
+      nBufSize += nCRLFLength;
+    }
+
+  LPTSTR pszBuf = text.GetBuffer (nBufSize);
+
+  if (nStartLine < nEndLine)
+    {
+      int nCount = m_aLines[nStartLine].m_nLength - nStartChar;
+      if (nCount > 0)
+        {
+          memcpy (pszBuf, m_aLines[nStartLine].m_pcLine + nStartChar, sizeof (TCHAR) * nCount);
+          pszBuf += nCount;
+        }
+      memcpy (pszBuf, pszCRLF, sizeof (TCHAR) * nCRLFLength);
+      pszBuf += nCRLFLength;
+      for (int I = nStartLine + 1; I < nEndLine; I++)
+        {
+          nCount = m_aLines[I].m_nLength;
+          if (nCount > 0)
+            {
+              memcpy (pszBuf, m_aLines[I].m_pcLine, sizeof (TCHAR) * nCount);
+              pszBuf += nCount;
+            }
+          memcpy (pszBuf, pszCRLF, sizeof (TCHAR) * nCRLFLength);
+          pszBuf += nCRLFLength;
+        }
+      if (nEndChar > 0)
+        {
+          memcpy (pszBuf, m_aLines[nEndLine].m_pcLine, sizeof (TCHAR) * nEndChar);
+          pszBuf += nEndChar;
+        }
+    }
+  else
+    {
+      int nCount = nEndChar - nStartChar;
+      memcpy (pszBuf, m_aLines[nStartLine].m_pcLine + nStartChar, sizeof (TCHAR) * nCount);
+      pszBuf += nCount;
+    }
+  pszBuf[0] = 0;
+  text.ReleaseBuffer ();
+  text.FreeExtra ();
+}
+
+void CCrystalTextBuffer::
+AddView (CCrystalTextView * pView)
+{
+  m_lpViews.AddTail (pView);
+}
+
+void CCrystalTextBuffer::
+RemoveView (CCrystalTextView * pView)
+{
+  POSITION pos = m_lpViews.GetHeadPosition ();
+  while (pos != NULL)
+    {
+      POSITION thispos = pos;
+      CCrystalTextView *pvw = m_lpViews.GetNext (pos);
+      if (pvw == pView)
+        {
+          m_lpViews.RemoveAt (thispos);
+          return;
+        }
+    }
+  ASSERT (FALSE);
+}
+
+CCrystalTextView::TextDefinition *CCrystalTextBuffer::
+RetypeViews (LPCTSTR lpszFileName)
+{
+  POSITION pos = m_lpViews.GetHeadPosition ();
+  CString sNew = GetExt (lpszFileName);
+  CCrystalTextView::TextDefinition *def = CCrystalTextView::GetTextType (sNew);
+  while (pos != NULL)
+    {
+      CCrystalTextView *pView = m_lpViews.GetNext (pos);
+      pView->SetTextType (def);
+    }
+  return def;
+}
+
+void CCrystalTextBuffer::
+UpdateViews (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwUpdateFlags, int nLineIndex /*= -1*/ )
+{
+  POSITION pos = m_lpViews.GetHeadPosition ();
+  while (pos != NULL)
+    {
+      CCrystalTextView *pView = m_lpViews.GetNext (pos);
+      pView->UpdateView (pSource, pContext, dwUpdateFlags, nLineIndex);
+    }
+}
+
+BOOL CCrystalTextBuffer::
+InternalDeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar, int nEndLine, int nEndChar)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  ASSERT (nStartLine >= 0 && nStartLine < m_aLines.GetSize ());
+  ASSERT (nStartChar >= 0 && nStartChar <= m_aLines[nStartLine].m_nLength);
+  ASSERT (nEndLine >= 0 && nEndLine < m_aLines.GetSize ());
+  ASSERT (nEndChar >= 0 && nEndChar <= m_aLines[nEndLine].m_nLength);
+  ASSERT (nStartLine < nEndLine || nStartLine == nEndLine && nStartChar < nEndChar);
+  if (m_bReadOnly)
+    return FALSE;
+
+  CDeleteContext context;
+  context.m_ptStart.y = nStartLine;
+  context.m_ptStart.x = nStartChar;
+  context.m_ptEnd.y = nEndLine;
+  context.m_ptEnd.x = nEndChar;
+  if (nStartLine == nEndLine)
+    {
+      SLineInfo & li = m_aLines[nStartLine];
+      if (nEndChar < li.m_nLength)
+        {
+          memcpy (li.m_pcLine + nStartChar, li.m_pcLine + nEndChar,
+                  sizeof (TCHAR) * (li.m_nLength - nEndChar));
+        }
+      li.m_nLength -= (nEndChar - nStartChar);
+
+         if (pSource!=NULL)
+               UpdateViews (pSource, &context, UPDATE_SINGLELINE | UPDATE_HORZRANGE, nStartLine);
+    }
+  else
+    {
+      int nRestCount = m_aLines[nEndLine].m_nLength - nEndChar;
+      LPTSTR pszRestChars = NULL;
+      if (nRestCount > 0)
+        {
+          pszRestChars = new TCHAR[nRestCount];
+          memcpy (pszRestChars, m_aLines[nEndLine].m_pcLine + nEndChar, nRestCount * sizeof (TCHAR));
+        }
+
+      int nDelCount = nEndLine - nStartLine;
+      for (int L = nStartLine + 1; L <= nEndLine; L++)
+        delete m_aLines[L].m_pcLine;
+      m_aLines.RemoveAt (nStartLine + 1, nDelCount);
+
+      //  nEndLine is no more valid
+      m_aLines[nStartLine].m_nLength = nStartChar;
+      if (nRestCount > 0)
+        {
+          AppendLine (nStartLine, pszRestChars, nRestCount);
+          delete pszRestChars;
+        }
+
+         if (pSource!=NULL)
+               UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE, nStartLine);
+    }
+
+  if (!m_bModified)
+    SetModified (TRUE);
+       //BEGIN SW
+       // remember current cursor position as last editing position
+       m_ptLastChange = context.m_ptStart;
+       //END SW
+  return TRUE;
+}
+
+BOOL CCrystalTextBuffer::
+InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+  ASSERT (nLine >= 0 && nLine < m_aLines.GetSize ());
+  ASSERT (nPos >= 0 && nPos <= m_aLines[nLine].m_nLength);
+  if (m_bReadOnly)
+    return FALSE;
+
+  CInsertContext context;
+  context.m_ptStart.x = nPos;
+  context.m_ptStart.y = nLine;
+
+  int nRestCount = m_aLines[nLine].m_nLength - nPos;
+  LPTSTR pszRestChars = NULL;
+  if (nRestCount > 0)
+    {
+      pszRestChars = new TCHAR[nRestCount];
+      memcpy (pszRestChars, m_aLines[nLine].m_pcLine + nPos, nRestCount * sizeof (TCHAR));
+      m_aLines[nLine].m_nLength = nPos;
+    }
+
+  int nCurrentLine = nLine;
+  BOOL bNewLines = FALSE;
+  int nTextPos;
+  for (;;)
+    {
+      nTextPos = 0;
+      while (pszText[nTextPos] != 0 && pszText[nTextPos] != _T ('\r'))
+        nTextPos++;
+
+      if (nCurrentLine == nLine)
+        {
+          AppendLine (nLine, pszText, nTextPos);
+        }
+      else
+        {
+          InsertLine (pszText, nTextPos, nCurrentLine);
+          bNewLines = TRUE;
+        }
+
+      if (pszText[nTextPos] == 0)
+        {
+          nEndLine = nCurrentLine;
+          nEndChar = m_aLines[nCurrentLine].m_nLength;
+          AppendLine (nCurrentLine, pszRestChars, nRestCount);
+          break;
+        }
+
+      nCurrentLine++;
+      nTextPos++;
+
+      if (pszText[nTextPos] == _T ('\n'))
+        {
+          nTextPos++;
+        }
+      else
+        {
+          ASSERT (FALSE);       //  Invalid line-end format passed
+
+        }
+
+      pszText += nTextPos;
+    }
+
+  if (pszRestChars != NULL)
+    delete pszRestChars;
+
+  context.m_ptEnd.x = nEndChar;
+  context.m_ptEnd.y = nEndLine;
+
+  if (pSource!=NULL)
+  {
+         if (bNewLines)
+               UpdateViews (pSource, &context, UPDATE_HORZRANGE | UPDATE_VERTRANGE, nLine);
+         else
+               UpdateViews (pSource, &context, UPDATE_SINGLELINE | UPDATE_HORZRANGE, nLine);
+  }
+
+  if (!m_bModified)
+    SetModified (TRUE);
+       //BEGIN SW
+       // remember current cursor position as last editing position
+       m_ptLastChange = context.m_ptEnd;
+       //END SW
+  return TRUE;
+}
+
+BOOL CCrystalTextBuffer::
+CanUndo ()
+{
+  ASSERT (m_nUndoPosition >= 0 && m_nUndoPosition <= m_aUndoBuf.GetSize ());
+  return m_nUndoPosition > 0;
+}
+
+BOOL CCrystalTextBuffer::
+CanRedo ()
+{
+  ASSERT (m_nUndoPosition >= 0 && m_nUndoPosition <= m_aUndoBuf.GetSize ());
+  return m_nUndoPosition < m_aUndoBuf.GetSize ();
+}
+
+POSITION CCrystalTextBuffer::
+GetUndoDescription (CString & desc, POSITION pos /*= NULL*/ )
+{
+  ASSERT (CanUndo ());          //  Please call CanUndo() first
+
+  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
+
+  int nPosition;
+  if (pos == NULL)
+    {
+      //  Start from beginning
+      nPosition = m_nUndoPosition;
+    }
+  else
+    {
+      nPosition = (int) pos;
+      ASSERT (nPosition > 0 && nPosition < m_nUndoPosition);
+      ASSERT ((m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);
+    }
+
+  //  Advance to next undo group
+  nPosition--;
+  while ((m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) == 0)
+    nPosition--;
+
+  //  Read description
+  if (!GetActionDescription (m_aUndoBuf[nPosition].m_nAction, desc))
+    desc.Empty ();              //  Use empty string as description
+
+  //  Now, if we stop at zero position, this will be the last action,
+  //  since we return (POSITION) nPosition
+  return (POSITION) nPosition;
+}
+
+POSITION CCrystalTextBuffer::
+GetRedoDescription (CString & desc, POSITION pos /*= NULL*/ )
+{
+  ASSERT (CanRedo ());          //  Please call CanRedo() before!
+
+  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
+  ASSERT ((m_aUndoBuf[m_nUndoPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);
+
+  int nPosition;
+  if (pos == NULL)
+    {
+      //  Start from beginning
+      nPosition = m_nUndoPosition;
+    }
+  else
+    {
+      nPosition = (int) pos;
+      ASSERT (nPosition > m_nUndoPosition);
+      ASSERT ((m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);
+    }
+
+  //  Read description
+  if (!GetActionDescription (m_aUndoBuf[nPosition].m_nAction, desc))
+    desc.Empty ();              //  Use empty string as description
+
+  //  Advance to next undo group
+  nPosition++;
+  while (nPosition < m_aUndoBuf.GetSize () &&
+        (m_aUndoBuf[nPosition].m_dwFlags & UNDO_BEGINGROUP) == 0)
+    nPosition--;
+
+  if (nPosition >= m_aUndoBuf.GetSize ())
+    return NULL;                //  No more redo actions!
+
+  return (POSITION) nPosition;
+}
+
+BOOL CCrystalTextBuffer::
+Undo (CPoint & ptCursorPos)
+{
+  ASSERT (CanUndo ());
+  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
+  for (;;)
+    {
+      m_nUndoPosition--;
+      const SUndoRecord & ur = m_aUndoBuf[m_nUndoPosition];
+      if (ur.m_dwFlags & UNDO_INSERT)
+        {
+#ifdef _ADVANCED_BUGCHECK
+          //  Try to ensure that we undoing correctly...
+          //  Just compare the text as it was before Undo operation
+          CString text;
+          GetText (ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x, text);
+          ASSERT (lstrcmp (text, ur.GetText ()) == 0);
+#endif
+          VERIFY (InternalDeleteText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x));
+          ptCursorPos = ur.m_ptStartPos;
+        }
+      else
+        {
+          int nEndLine, nEndChar;
+          VERIFY (InternalInsertText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.GetText (), nEndLine, nEndChar));
+#ifdef _ADVANCED_BUGCHECK
+          ASSERT (ur.m_ptEndPos.y == nEndLine);
+          ASSERT (ur.m_ptEndPos.x == nEndChar);
+#endif
+          ptCursorPos = ur.m_ptEndPos;
+        }
+      if (ur.m_dwFlags & UNDO_BEGINGROUP)
+        break;
+    }
+  if (m_bModified && m_nSyncPosition == m_nUndoPosition)
+    SetModified (FALSE);
+  if (!m_bModified && m_nSyncPosition != m_nUndoPosition)
+    SetModified (TRUE);
+  return TRUE;
+}
+
+BOOL CCrystalTextBuffer::
+Redo (CPoint & ptCursorPos)
+{
+  ASSERT (CanRedo ());
+  ASSERT ((m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
+  ASSERT ((m_aUndoBuf[m_nUndoPosition].m_dwFlags & UNDO_BEGINGROUP) != 0);
+  for (;;)
+    {
+      const SUndoRecord & ur = m_aUndoBuf[m_nUndoPosition];
+      if (ur.m_dwFlags & UNDO_INSERT)
+        {
+          int nEndLine, nEndChar;
+          VERIFY (InternalInsertText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.GetText (), nEndLine, nEndChar));
+#ifdef _ADVANCED_BUGCHECK
+          ASSERT (ur.m_ptEndPos.y == nEndLine);
+          ASSERT (ur.m_ptEndPos.x == nEndChar);
+#endif
+          ptCursorPos = ur.m_ptEndPos;
+        }
+      else
+        {
+#ifdef _ADVANCED_BUGCHECK
+          CString text;
+          GetText (ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x, text);
+          ASSERT (lstrcmp (text, ur.GetText ()) == 0);
+#endif
+          VERIFY (InternalDeleteText (NULL, ur.m_ptStartPos.y, ur.m_ptStartPos.x, ur.m_ptEndPos.y, ur.m_ptEndPos.x));
+          ptCursorPos = ur.m_ptStartPos;
+        }
+      m_nUndoPosition++;
+      if (m_nUndoPosition == m_aUndoBuf.GetSize ())
+        break;
+      if ((m_aUndoBuf[m_nUndoPosition].m_dwFlags & UNDO_BEGINGROUP) != 0)
+        break;
+    }
+  if (m_bModified && m_nSyncPosition == m_nUndoPosition)
+    SetModified (FALSE);
+  if (!m_bModified && m_nSyncPosition != m_nUndoPosition)
+    SetModified (TRUE);
+  return TRUE;
+}
+
+//  [JRT] Support For Descriptions On Undo/Redo Actions
+void CCrystalTextBuffer::
+AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos, LPCTSTR pszText, int nActionType)
+{
+  //  Forgot to call BeginUndoGroup()?
+  ASSERT (m_bUndoGroup);
+  ASSERT (m_aUndoBuf.GetSize () == 0 || (m_aUndoBuf[0].m_dwFlags & UNDO_BEGINGROUP) != 0);
+
+  //  Strip unnecessary undo records (edit after undo)
+  int nBufSize = m_aUndoBuf.GetSize ();
+  if (m_nUndoPosition < nBufSize)
+    {
+      for (int I = m_nUndoPosition; I < nBufSize; I++)
+        m_aUndoBuf[I].FreeText ();
+      m_aUndoBuf.SetSize (m_nUndoPosition);
+    }
+
+  //  If undo buffer size is close to critical, remove the oldest records
+  ASSERT (m_aUndoBuf.GetSize () <= m_nUndoBufSize);
+  nBufSize = m_aUndoBuf.GetSize ();
+  if (nBufSize >= m_nUndoBufSize)
+    {
+      int nIndex = 0;
+      for (;;)
+        {
+          m_aUndoBuf[nIndex].FreeText ();
+          nIndex++;
+          if (nIndex == nBufSize || (m_aUndoBuf[nIndex].m_dwFlags & UNDO_BEGINGROUP) != 0)
+            break;
+        }
+      m_aUndoBuf.RemoveAt (0, nIndex);
+    }
+  ASSERT (m_aUndoBuf.GetSize () < m_nUndoBufSize);
+
+  //  Add new record
+  SUndoRecord ur;
+  ur.m_dwFlags = bInsert ? UNDO_INSERT : 0;
+  ur.m_nAction = nActionType;
+  if (m_bUndoBeginGroup)
+    {
+      ur.m_dwFlags |= UNDO_BEGINGROUP;
+      m_bUndoBeginGroup = FALSE;
+    }
+  ur.m_ptStartPos = ptStartPos;
+  ur.m_ptEndPos = ptEndPos;
+  ur.SetText (pszText);
+
+  m_aUndoBuf.Add (ur);
+  m_nUndoPosition = m_aUndoBuf.GetSize ();
+
+  ASSERT (m_aUndoBuf.GetSize () <= m_nUndoBufSize);
+}
+
+BOOL CCrystalTextBuffer::
+InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText,
+            int &nEndLine, int &nEndChar, int nAction, BOOL bUpdate /*=TRUE*/)
+{
+       if (!InternalInsertText (bUpdate? pSource:NULL, nLine, nPos, pszText, nEndLine, nEndChar))
+    return FALSE;
+
+  BOOL bGroupFlag = FALSE;
+  if (!m_bUndoGroup)
+    {
+      BeginUndoGroup ();
+      bGroupFlag = TRUE;
+    }
+  AddUndoRecord (TRUE, CPoint (nPos, nLine), CPoint (nEndChar, nEndLine), pszText, nAction);
+  if (bGroupFlag)
+    FlushUndoGroup (pSource);
+  return TRUE;
+}
+
+BOOL CCrystalTextBuffer::
+DeleteText (CCrystalTextView * pSource, int nStartLine, int nStartChar,
+            int nEndLine, int nEndChar, int nAction, BOOL bUpdate /*=TRUE*/)
+{
+  CString sTextToDelete;
+  GetText (nStartLine, nStartChar, nEndLine, nEndChar, sTextToDelete);
+
+  if (!InternalDeleteText (bUpdate? pSource:NULL, nStartLine, nStartChar, nEndLine, nEndChar))
+    return FALSE;
+
+  BOOL bGroupFlag = FALSE;
+  if (!m_bUndoGroup)
+    {
+      BeginUndoGroup ();
+      bGroupFlag = TRUE;
+    }
+  AddUndoRecord (FALSE, CPoint (nStartChar, nStartLine), CPoint (nEndChar, nEndLine), sTextToDelete, nAction);
+  if (bGroupFlag)
+    FlushUndoGroup (pSource);
+  return TRUE;
+}
+
+BOOL CCrystalTextBuffer::
+GetActionDescription (int nAction, CString & desc)
+{
+  HINSTANCE hOldResHandle = AfxGetResourceHandle ();
+#ifdef CRYSEDIT_RES_HANDLE
+  AfxSetResourceHandle (CRYSEDIT_RES_HANDLE);
+#else
+  if (CCrystalTextView::s_hResourceInst != NULL)
+    AfxSetResourceHandle (CCrystalTextView::s_hResourceInst);
+#endif
+  BOOL bSuccess = FALSE;
+  switch (nAction)
+    {
+    case CE_ACTION_PASTE:
+      bSuccess = desc.LoadString (IDS_EDITOP_PASTE);
+      break;
+    case CE_ACTION_DELSEL:
+      bSuccess = desc.LoadString (IDS_EDITOP_DELSELECTION);
+      break;
+    case CE_ACTION_CUT:
+      bSuccess = desc.LoadString (IDS_EDITOP_CUT);
+      break;
+    case CE_ACTION_TYPING:
+      bSuccess = desc.LoadString (IDS_EDITOP_TYPING);
+      break;
+    case CE_ACTION_BACKSPACE:
+      bSuccess = desc.LoadString (IDS_EDITOP_BACKSPACE);
+      break;
+    case CE_ACTION_INDENT:
+      bSuccess = desc.LoadString (IDS_EDITOP_INDENT);
+      break;
+    case CE_ACTION_DRAGDROP:
+      bSuccess = desc.LoadString (IDS_EDITOP_DRAGDROP);
+      break;
+    case CE_ACTION_REPLACE:
+      bSuccess = desc.LoadString (IDS_EDITOP_REPLACE);
+      break;
+    case CE_ACTION_DELETE:
+      bSuccess = desc.LoadString (IDS_EDITOP_DELETE);
+      break;
+    case CE_ACTION_AUTOINDENT:
+      bSuccess = desc.LoadString (IDS_EDITOP_AUTOINDENT);
+      break;
+    case CE_ACTION_AUTOCOMPLETE:
+      bSuccess = desc.LoadString (IDS_EDITOP_AUTOCOMPLETE);
+      break;
+    case CE_ACTION_AUTOEXPAND:
+      bSuccess = desc.LoadString (IDS_EDITOP_AUTOEXPAND);
+      break;
+    case CE_ACTION_LOWERCASE:
+      bSuccess = desc.LoadString (IDS_EDITOP_LOWERCASE);
+      break;
+    case CE_ACTION_UPPERCASE:
+      bSuccess = desc.LoadString (IDS_EDITOP_UPPERCASE);
+      break;
+    case CE_ACTION_SWAPCASE:
+      bSuccess = desc.LoadString (IDS_EDITOP_SWAPCASE);
+      break;
+    case CE_ACTION_CAPITALIZE:
+      bSuccess = desc.LoadString (IDS_EDITOP_CAPITALIZE);
+      break;
+    case CE_ACTION_SENTENCIZE:
+      bSuccess = desc.LoadString (IDS_EDITOP_SENTENCIZE);
+      break;
+    case CE_ACTION_RECODE:
+      bSuccess = desc.LoadString (IDS_EDITOP_RECODE);
+      break;
+    case CE_ACTION_SPELL:
+      bSuccess = desc.LoadString (IDS_EDITOP_SPELL);
+      break;
+    default: /* case CE_ACTION_UNKNOWN: */
+      bSuccess = desc.LoadString (IDS_EDITOP_UNKNOWN);
+    }
+  AfxSetResourceHandle (hOldResHandle);
+  return bSuccess;
+}
+
+void CCrystalTextBuffer::
+SetModified (BOOL bModified /*= TRUE*/ )
+{
+  m_bModified = bModified;
+}
+
+void CCrystalTextBuffer::
+BeginUndoGroup (BOOL bMergeWithPrevious /*= FALSE*/ )
+{
+  ASSERT (!m_bUndoGroup);
+  m_bUndoGroup = TRUE;
+  m_bUndoBeginGroup = m_nUndoPosition == 0 || !bMergeWithPrevious;
+}
+
+void CCrystalTextBuffer::
+FlushUndoGroup (CCrystalTextView * pSource)
+{
+  ASSERT (m_bUndoGroup);
+  if (pSource != NULL)
+    {
+      ASSERT (m_nUndoPosition == m_aUndoBuf.GetSize ());
+      if (m_nUndoPosition > 0)
+        {
+          m_bUndoBeginGroup = TRUE;
+          pSource->OnEditOperation (m_aUndoBuf[m_nUndoPosition - 1].m_nAction, m_aUndoBuf[m_nUndoPosition - 1].GetText ());
+        }
+    }
+  m_bUndoGroup = FALSE;
+}
+
+int CCrystalTextBuffer::
+FindNextBookmarkLine (int nCurrentLine)
+{
+  BOOL bWrapIt = TRUE;
+  DWORD dwFlags = GetLineFlags (nCurrentLine);
+  if ((dwFlags & LF_BOOKMARKS) != 0)
+    nCurrentLine++;
+
+  int nSize = m_aLines.GetSize ();
+  for (;;)
+    {
+      while (nCurrentLine < nSize)
+        {
+          if ((m_aLines[nCurrentLine].m_dwFlags & LF_BOOKMARKS) != 0)
+            return nCurrentLine;
+          // Keep going
+          nCurrentLine++;
+        }
+      // End of text reached
+      if (!bWrapIt)
+        return -1;
+
+      // Start from the beginning of text
+      bWrapIt = FALSE;
+      nCurrentLine = 0;
+    }
+  return -1;
+}
+
+int CCrystalTextBuffer::
+FindPrevBookmarkLine (int nCurrentLine)
+{
+  BOOL bWrapIt = TRUE;
+  DWORD dwFlags = GetLineFlags (nCurrentLine);
+  if ((dwFlags & LF_BOOKMARKS) != 0)
+    nCurrentLine--;
+
+  int nSize = m_aLines.GetSize ();
+  for (;;)
+    {
+      while (nCurrentLine >= 0)
+        {
+          if ((m_aLines[nCurrentLine].m_dwFlags & LF_BOOKMARKS) != 0)
+            return nCurrentLine;
+          // Keep moving up
+          nCurrentLine--;
+        }
+      // Beginning of text reached
+      if (!bWrapIt)
+        return -1;
+
+      // Start from the end of text
+      bWrapIt = FALSE;
+      nCurrentLine = nSize - 1;
+    }
+  return -1;
+}
+
+BOOL CCrystalTextBuffer::
+IsMBSLead (int nLine, int nCol)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+#ifdef _UNICODE
+  LPCTSTR string = (LPCTSTR) GetLineChars (nLine);
+  LPCTSTR current = string + nCol;
+  return FALSE;
+#else // _UNICODE
+  const unsigned char *string = (const unsigned char *) GetLineChars (nLine);
+  const unsigned char *current = string + nCol;
+  if (_ismbslead (string, current) < 0)
+    return TRUE;
+  return FALSE;
+#endif // _UNICODE
+}
+
+BOOL CCrystalTextBuffer::
+IsMBSTrail (int nLine, int nCol)
+{
+  ASSERT (m_bInit);             //  Text buffer not yet initialized.
+  //  You must call InitNew() or LoadFromFile() first!
+
+#ifdef _UNICODE
+  LPCTSTR string = (LPCTSTR) GetLineChars (nLine);
+  LPCTSTR current = string + nCol;
+  return FALSE;
+#else // _UNICODE
+  const unsigned char *string = (const unsigned char *) GetLineChars (nLine);
+  const unsigned char *current = string + nCol;
+  if (_ismbstrail (string, current) < 0)
+    return TRUE;
+  return FALSE;
+#endif // _UNICODE
+}
+
+//BEGIN SW
+CPoint CCrystalTextBuffer::GetLastChangePos() const
+{
+       return m_ptLastChange;
+}
+//END SW
diff --git a/Src/editlib/ccrystaltextbuffer.h b/Src/editlib/ccrystaltextbuffer.h
new file mode 100644 (file)
index 0000000..40efcae
--- /dev/null
@@ -0,0 +1,335 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ccrystaltextbuffer.h
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Interface of the CCrystalTextBuffer class, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CCRYSTALTEXTBUFFER_H__AD7F2F49_6CB3_11D2_8C32_0080ADB86836__INCLUDED_)
+#define AFX_CCRYSTALTEXTBUFFER_H__AD7F2F49_6CB3_11D2_8C32_0080ADB86836__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "ccrystaltextview.h"
+
+#ifndef __AFXTEMPL_H__
+#pragma message("Include <afxtempl.h> in your stdafx.h to avoid this message")
+#include <afxtempl.h>
+#endif
+
+#define UNDO_DESCRIP_BUF        32
+
+enum LINEFLAGS
+{
+  LF_BOOKMARK_FIRST = 0x00000001L,
+  LF_EXECUTION = 0x00010000L,
+  LF_BREAKPOINT = 0x00020000L,
+  LF_COMPILATION_ERROR = 0x00040000L,
+  LF_BOOKMARKS = 0x00080000L,
+  LF_INVALID_BREAKPOINT = 0x00100000L,
+  LF_DIFF = 0x00200000L,
+  LF_DELETED = 0x00400000L,
+  LF_LEFT_ONLY = 0x00800000L,
+  LF_RIGHT_ONLY = 0x01000000L
+};
+#define LF_WINMERGE_FLAGS      0x01e00000
+
+#define LF_BOOKMARK(id)     (LF_BOOKMARK_FIRST << id)
+
+enum CRLFSTYLE
+{
+  CRLF_STYLE_AUTOMATIC = -1,
+  CRLF_STYLE_DOS = 0,
+  CRLF_STYLE_UNIX = 1,
+  CRLF_STYLE_MAC = 2
+};
+
+enum
+{
+  CE_ACTION_UNKNOWN = 0,
+  CE_ACTION_PASTE = 1,
+  CE_ACTION_DELSEL = 2,
+  CE_ACTION_CUT = 3,
+  CE_ACTION_TYPING = 4,
+  CE_ACTION_BACKSPACE = 5,
+  CE_ACTION_INDENT = 6,
+  CE_ACTION_DRAGDROP = 7,
+  CE_ACTION_REPLACE = 8,
+  CE_ACTION_DELETE = 9,
+  CE_ACTION_AUTOINDENT = 10,
+  CE_ACTION_AUTOCOMPLETE = 11,
+  CE_ACTION_AUTOEXPAND = 12,
+  CE_ACTION_LOWERCASE = 13,
+  CE_ACTION_UPPERCASE = 14,
+  CE_ACTION_SWAPCASE = 15,
+  CE_ACTION_CAPITALIZE = 16,
+  CE_ACTION_SENTENCIZE = 17,
+  CE_ACTION_RECODE  = 18, 
+  CE_ACTION_SPELL = 19
+                         //  ...
+                         //  Expandable: user actions allowed
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CUpdateContext class
+
+class EDITPADC_CLASS CUpdateContext
+  {
+public :
+    virtual void RecalcPoint (CPoint & ptPoint) = 0;
+  };
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextBuffer command target
+
+class EDITPADC_CLASS CCrystalTextBuffer : public CCmdTarget
+  {
+public:
+    DECLARE_DYNCREATE (CCrystalTextBuffer)
+
+    int m_nSourceEncoding;
+    static int m_nDefaultEncoding;
+
+protected :
+    BOOL m_bInit;
+    BOOL m_bReadOnly;
+    BOOL m_bModified;
+    int m_nCRLFMode;
+    BOOL m_bCreateBackupFile;
+    int m_nUndoBufSize;
+    int FindLineWithFlag (DWORD dwFlag);
+
+protected :
+#pragma pack(push, 1)
+    //  Nested class declarations
+    struct SLineInfo
+      {
+        TCHAR *m_pcLine;
+        int m_nLength, m_nMax;
+        DWORD m_dwFlags;
+
+        SLineInfo ()
+        {
+          memset (this, 0, sizeof (SLineInfo));
+        };
+      };
+
+    enum
+    {
+      UNDO_INSERT = 0x0001,
+      UNDO_BEGINGROUP = 0x0100
+    };
+
+    //  [JRT] Support For Descriptions On Undo/Redo Actions
+    struct SUndoRecord
+      {
+        DWORD m_dwFlags;
+
+        CPoint m_ptStartPos, m_ptEndPos;  //  Block of text participating
+
+        int m_nAction;            //  For information only: action type
+
+private :
+        //  TCHAR   *m_pcText;
+        //  Since in most cases we have 1 character here,
+        //  we should invent a better way. Note: 2 * sizeof(WORD) <= sizeof(TCHAR*)
+        //
+        //  Here we will use the following trick: on Win32 platforms high-order word
+        //  of any pointer will be != 0. So we can store 1 character strings without
+        //  allocating memory.
+        //
+
+        union
+          {
+            TCHAR *m_pszText;     //  For cases when we have > 1 character strings
+
+            TCHAR m_szText[2];    //  For single-character strings
+
+          };
+
+public :
+        //  constructor/destructor for this struct
+        SUndoRecord ()
+        {
+          memset (this, 0, sizeof (SUndoRecord));
+        };
+
+        void SetText (LPCTSTR pszText);
+        void FreeText ();
+
+        LPCTSTR GetText () const
+        {
+          if (HIWORD ((DWORD) m_pszText) != 0)
+            return m_pszText;
+          return m_szText;
+        };
+      };
+
+#pragma pack(pop)
+
+class EDITPADC_CLASS CInsertContext : public CUpdateContext
+      {
+public :
+        CPoint m_ptStart, m_ptEnd;
+        virtual void RecalcPoint (CPoint & ptPoint);
+      };
+
+class EDITPADC_CLASS CDeleteContext : public CUpdateContext
+      {
+public :
+        CPoint m_ptStart, m_ptEnd;
+        virtual void RecalcPoint (CPoint & ptPoint);
+      };
+
+    //  Lines of text
+    CArray < SLineInfo, SLineInfo & >m_aLines;
+
+    //  Undo
+    CArray < SUndoRecord, SUndoRecord & >m_aUndoBuf;
+    int m_nUndoPosition;
+    int m_nSyncPosition;
+    BOOL m_bUndoGroup, m_bUndoBeginGroup;
+
+       //BEGIN SW
+       /** Position where the last change was made. */
+       CPoint m_ptLastChange;
+       //END SW
+
+    //  Connected views
+    CList < CCrystalTextView *, CCrystalTextView * >m_lpViews;
+
+    //  Helper methods
+    void InsertLine (LPCTSTR pszLine, int nLength = -1, int nPosition = -1);
+    void AppendLine (int nLineIndex, LPCTSTR pszChars, int nLength = -1);
+
+    //  Implementation
+    BOOL InternalInsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar);
+    BOOL InternalDeleteText (CCrystalTextView * pSource, int nStartLine, int nStartPos, int nEndLine, int nEndPos);
+
+    //  [JRT] Support For Descriptions On Undo/Redo Actions
+    void AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
+                        LPCTSTR pszText, int nActionType = CE_ACTION_UNKNOWN);
+
+    //  Overridable: provide action description
+    virtual BOOL GetActionDescription (int nAction, CString & desc);
+
+    // Operations
+public :
+    //  Construction/destruction code
+    CCrystalTextBuffer ();
+    ~CCrystalTextBuffer ();
+
+    //  Basic functions
+    BOOL InitNew (int nCrlfStyle = CRLF_STYLE_DOS);
+    BOOL LoadFromFile (LPCTSTR pszFileName, int nCrlfStyle = CRLF_STYLE_AUTOMATIC);
+    BOOL SaveToFile (LPCTSTR pszFileName, int nCrlfStyle = CRLF_STYLE_AUTOMATIC, BOOL bClearModifiedFlag = TRUE);
+    void FreeAll ();
+
+    //  'Dirty' flag
+    virtual void SetModified (BOOL bModified = TRUE);
+    BOOL IsModified () const;
+
+    //  Connect/disconnect views
+    void AddView (CCrystalTextView * pView);
+    void RemoveView (CCrystalTextView * pView);
+
+    //  Text access functions
+    int GetLineCount ();
+    int GetLineLength (int nLine);
+    LPTSTR GetLineChars (int nLine);
+    DWORD GetLineFlags (int nLine);
+    int GetLineWithFlag (DWORD dwFlag);
+    void SetLineFlag (int nLine, DWORD dwFlag, BOOL bSet, BOOL bRemoveFromPreviousLine = TRUE, BOOL bUpdate=TRUE);
+    void GetText (int nStartLine, int nStartChar, int nEndLine, int nEndChar, CString & text, LPCTSTR pszCRLF = NULL);
+
+    //  Attributes
+    int GetCRLFMode ();
+    void SetCRLFMode (int nCRLFMode);
+    BOOL GetReadOnly () const;
+    void SetReadOnly (BOOL bReadOnly = TRUE);
+
+    //  Text modification functions
+    BOOL InsertText (CCrystalTextView * pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar, int nAction = CE_ACTION_UNKNOWN, BOOL bUpdate =TRUE);
+    BOOL DeleteText (CCrystalTextView * pSource, int nStartLine, int nStartPos, int nEndLine, int nEndPos, int nAction = CE_ACTION_UNKNOWN, BOOL bUpdate =TRUE);
+
+    //  Undo/Redo
+    BOOL CanUndo ();
+    BOOL CanRedo ();
+    BOOL Undo (CPoint & ptCursorPos);
+    BOOL Redo (CPoint & ptCursorPos);
+
+    //  Undo grouping
+    void BeginUndoGroup (BOOL bMergeWithPrevious = FALSE);
+    void FlushUndoGroup (CCrystalTextView * pSource);
+
+       //BEGIN SW
+       /**
+       Returns the position where the last changes where made.
+       */
+       CPoint GetLastChangePos() const;
+       //END SW
+
+    //  Browse undo sequence
+    POSITION GetUndoDescription (CString & desc, POSITION pos = NULL);
+    POSITION GetRedoDescription (CString & desc, POSITION pos = NULL);
+
+    //  Notify all connected views about changes in name of file
+    CCrystalTextView::TextDefinition *RetypeViews (LPCTSTR lpszFileName);
+    //  Notify all connected views about changes in text
+    void UpdateViews (CCrystalTextView * pSource, CUpdateContext * pContext,
+                      DWORD dwUpdateFlags, int nLineIndex = -1);
+
+    // More bookmarks
+    int FindNextBookmarkLine (int nCurrentLine = 0);
+    int FindPrevBookmarkLine (int nCurrentLine = 0);
+
+    BOOL IsMBSLead (int nLine, int nCol);
+    BOOL IsMBSTrail (int nLine, int nCol);
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CCrystalTextBuffer)
+    //}}AFX_VIRTUAL
+
+    // Implementation
+protected :
+    // Generated message map functions
+    //{{AFX_MSG(CCrystalTextBuffer)
+    //}}AFX_MSG
+
+    DECLARE_MESSAGE_MAP ()
+  };
+
+#if ! (defined(CE_FROM_DLL) || defined(CE_DLL_BUILD))
+#include "ccrystaltextbuffer.inl"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CCRYSTALTEXTBUFFER_H__AD7F2F49_6CB3_11D2_8C32_0080ADB86836__INCLUDED_)
diff --git a/Src/editlib/ccrystaltextbuffer.inl b/Src/editlib/ccrystaltextbuffer.inl
new file mode 100644 (file)
index 0000000..4a9212b
--- /dev/null
@@ -0,0 +1,38 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       CCrystalTextBuffer.inl
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Inline functions of Crystal Edit classes
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __CCrystalTextBuffer_INL_INCLUDED
+#define __CCrystalTextBuffer_INL_INCLUDED
+
+#include "CCrystalTextBuffer.h"
+
+inline BOOL CCrystalTextBuffer::
+IsModified ()
+const
+{
+  return m_bModified;
+}
+
+#endif
diff --git a/Src/editlib/ccrystaltextview.cpp b/Src/editlib/ccrystaltextview.cpp
new file mode 100644 (file)
index 0000000..038d682
--- /dev/null
@@ -0,0 +1,5202 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ccrystaltextview.cpp
+//  Version:    1.2.0.5
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CCrystalTextView class, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  17-Feb-99
+//  FIX:    missing UpdateCaret() in CCrystalTextView::SetFont
+//  FIX:    missing UpdateCaret() in CCrystalTextView::RecalcVertScrollBar
+//  FIX:    mistype in CCrystalTextView::RecalcPageLayouts + instead of +=
+//  FIX:    removed condition 'm_nLineHeight < 20' in
+//      CCrystalTextView::CalcLineCharDim(). This caused painting defects
+//      when using very small fonts.
+//
+//  FEATURE:    Some experiments with smooth scrolling, controlled by
+//      m_bSmoothScroll member variable, by default turned off.
+//      See ScrollToLine function for implementation details.
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  21-Feb-99
+//      Paul Selormey, James R. Twine
+//  +   FEATURE: description for Undo/Redo actions
+//  +   FEATURE: multiple MSVC-like bookmarks
+//  +   FEATURE: 'Disable backspace at beginning of line' option
+//  +   FEATURE: 'Disable drag-n-drop editing' option
+//
+//  +   FIX:  ResetView() now virtual
+//  +   FEATURE: Added OnEditOperation() virtual: base for auto-indent,
+//      smart indent etc.
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: regular expressions, go to line and things ...
+//  +   FEATURE: plenty of syntax highlighting definitions
+//  +   FEATURE: corrected bug in syntax highlighting C comments
+//  +   FEATURE: extended registry support for saving settings
+//  +   FEATURE: some other things I've forgotten ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//     01-Jun-99 to 31-Aug-99
+//             Sven Wiegand (search for "//BEGIN SW" to find my changes):
+//
+//     + FEATURE: support for language switching on the fly with class 
+//                     CCrystalParser
+//     +       FEATURE: word wrapping
+//     + FIX:  Setting m_nIdealCharPos, when choosing cursor position by mouse
+//     + FIX:  Backward search
+//     + FEATURE: incremental search
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//     24-Oct-99
+//             Sven Wiegand
+//
+//     + FIX: Opening large files won't crash anymore and will go very fast
+//            (removed call to RecalcVertScrollBar() in WrapLineCached())
+//     + FIX: Problems with repainting and cursor-position by resizing window 
+//            fixed by adding call to ScrollToSubLine() in OnSize().
+//     + FEATURE: Supporting [Return] to exit incremental-search-mode
+//                  (see OnChar())
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include <malloc.h>
+#include "editcmd.h"
+#include "editreg.h"
+#include "ccrystaltextview.h"
+#include "ccrystaltextbuffer.h"
+#include "cfindtextdlg.h"
+#include "fpattern.h"
+#include "filesup.h"
+#include "registry.h"
+#include "gotodlg.h"
+
+#ifndef __AFXPRIV_H__
+#pragma message("Include <afxpriv.h> in your stdafx.h to avoid this message")
+#include <afxpriv.h>
+#endif
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define TAB_CHARACTER               _T('\xBB')
+#define SPACE_CHARACTER             _T('\x95')
+#define DEFAULT_PRINT_MARGIN        1000    //  10 millimeters
+
+#define SMOOTH_SCROLL_FACTOR        6
+
+#pragma warning ( disable : 4100 )
+////////////////////////////////////////////////////////////////////////////
+// CCrystalTextView
+
+LOGFONT CCrystalTextView::m_LogFont;
+
+IMPLEMENT_DYNCREATE (CCrystalTextView, CView)
+
+HINSTANCE CCrystalTextView::s_hResourceInst = NULL;
+
+BEGIN_MESSAGE_MAP (CCrystalTextView, CView)
+//{{AFX_MSG_MAP(CCrystalTextView)
+ON_WM_DESTROY ()
+ON_WM_ERASEBKGND ()
+ON_WM_SIZE ()
+ON_WM_VSCROLL ()
+ON_WM_SETCURSOR ()
+ON_WM_LBUTTONDOWN ()
+ON_WM_SETFOCUS ()
+ON_WM_HSCROLL ()
+ON_WM_LBUTTONUP ()
+ON_WM_MOUSEMOVE ()
+ON_WM_TIMER ()
+ON_WM_KILLFOCUS ()
+ON_WM_LBUTTONDBLCLK ()
+ON_COMMAND (ID_EDIT_COPY, OnEditCopy)
+ON_UPDATE_COMMAND_UI (ID_EDIT_COPY, OnUpdateEditCopy)
+ON_COMMAND (ID_EDIT_SELECT_ALL, OnEditSelectAll)
+ON_UPDATE_COMMAND_UI (ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll)
+ON_WM_RBUTTONDOWN ()
+ON_WM_SYSCOLORCHANGE ()
+ON_WM_CREATE ()
+ON_COMMAND (ID_EDIT_FIND, OnEditFind)
+ON_COMMAND (ID_EDIT_REPEAT, OnEditRepeat)
+ON_UPDATE_COMMAND_UI (ID_EDIT_REPEAT, OnUpdateEditRepeat)
+ON_COMMAND (ID_EDIT_FIND_PREVIOUS, OnEditFindPrevious)
+ON_UPDATE_COMMAND_UI (ID_EDIT_FIND_PREVIOUS, OnUpdateEditFindPrevious)
+ON_WM_MOUSEWHEEL ()
+//}}AFX_MSG_MAP
+ON_COMMAND (ID_EDIT_CHAR_LEFT, OnCharLeft)
+ON_COMMAND (ID_EDIT_EXT_CHAR_LEFT, OnExtCharLeft)
+ON_COMMAND (ID_EDIT_CHAR_RIGHT, OnCharRight)
+ON_COMMAND (ID_EDIT_EXT_CHAR_RIGHT, OnExtCharRight)
+ON_COMMAND (ID_EDIT_WORD_LEFT, OnWordLeft)
+ON_COMMAND (ID_EDIT_EXT_WORD_LEFT, OnExtWordLeft)
+ON_COMMAND (ID_EDIT_WORD_RIGHT, OnWordRight)
+ON_COMMAND (ID_EDIT_EXT_WORD_RIGHT, OnExtWordRight)
+ON_COMMAND (ID_EDIT_LINE_UP, OnLineUp)
+ON_COMMAND (ID_EDIT_EXT_LINE_UP, OnExtLineUp)
+ON_COMMAND (ID_EDIT_LINE_DOWN, OnLineDown)
+ON_COMMAND (ID_EDIT_EXT_LINE_DOWN, OnExtLineDown)
+ON_COMMAND (ID_EDIT_SCROLL_UP, ScrollUp)
+ON_COMMAND (ID_EDIT_SCROLL_DOWN, ScrollDown)
+ON_COMMAND (ID_EDIT_PAGE_UP, OnPageUp)
+ON_COMMAND (ID_EDIT_EXT_PAGE_UP, OnExtPageUp)
+ON_COMMAND (ID_EDIT_PAGE_DOWN, OnPageDown)
+ON_COMMAND (ID_EDIT_EXT_PAGE_DOWN, OnExtPageDown)
+ON_COMMAND (ID_EDIT_LINE_END, OnLineEnd)
+ON_COMMAND (ID_EDIT_EXT_LINE_END, OnExtLineEnd)
+ON_COMMAND (ID_EDIT_HOME, OnHome)
+ON_COMMAND (ID_EDIT_EXT_HOME, OnExtHome)
+ON_COMMAND (ID_EDIT_TEXT_BEGIN, OnTextBegin)
+ON_COMMAND (ID_EDIT_EXT_TEXT_BEGIN, OnExtTextBegin)
+ON_COMMAND (ID_EDIT_TEXT_END, OnTextEnd)
+ON_COMMAND (ID_EDIT_EXT_TEXT_END, OnExtTextEnd)
+//  Standard printing commands
+ON_COMMAND (ID_FILE_PAGE_SETUP, OnFilePageSetup)
+ON_COMMAND (ID_FILE_PRINT, CView::OnFilePrint)
+ON_COMMAND (ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
+ON_COMMAND (ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
+//  Status
+ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_CRLF, OnUpdateIndicatorCRLF)
+ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_POSITION, OnUpdateIndicatorPosition)
+//  Bookmarks
+ON_COMMAND_RANGE (ID_EDIT_TOGGLE_BOOKMARK0, ID_EDIT_TOGGLE_BOOKMARK9, OnToggleBookmark)
+ON_COMMAND_RANGE (ID_EDIT_GO_BOOKMARK0, ID_EDIT_GO_BOOKMARK9, OnGoBookmark)
+ON_COMMAND (ID_EDIT_CLEAR_BOOKMARKS, OnClearBookmarks)
+// More Bookmarks
+ON_COMMAND (ID_EDIT_TOGGLE_BOOKMARK, OnToggleBookmark)
+ON_COMMAND (ID_EDIT_GOTO_NEXT_BOOKMARK, OnNextBookmark)
+ON_COMMAND (ID_EDIT_GOTO_PREV_BOOKMARK, OnPrevBookmark)
+ON_COMMAND (ID_EDIT_CLEAR_ALL_BOOKMARKS, OnClearAllBookmarks)
+ON_UPDATE_COMMAND_UI (ID_EDIT_GOTO_NEXT_BOOKMARK, OnUpdateNextBookmark)
+ON_UPDATE_COMMAND_UI (ID_EDIT_GOTO_PREV_BOOKMARK, OnUpdatePrevBookmark)
+ON_UPDATE_COMMAND_UI (ID_EDIT_CLEAR_ALL_BOOKMARKS, OnUpdateClearAllBookmarks)
+// Ferdi's source type chnages
+ON_COMMAND_RANGE (ID_SOURCE_PLAIN, ID_SOURCE_TEX, OnSourceType)
+ON_UPDATE_COMMAND_UI_RANGE (ID_SOURCE_PLAIN, ID_SOURCE_TEX, OnUpdateSourceType)
+ON_COMMAND (ID_EDIT_MATCHBRACE, OnMatchBrace)
+ON_UPDATE_COMMAND_UI (ID_EDIT_MATCHBRACE, OnUpdateMatchBrace)
+ON_COMMAND (ID_EDIT_GOTO, OnEditGoTo)
+ON_UPDATE_COMMAND_UI (ID_VIEW_TOGGLE_SRC_HDR, OnUpdateToggleSourceHeader)
+ON_COMMAND (ID_VIEW_TOGGLE_SRC_HDR, OnToggleSourceHeader)
+ON_UPDATE_COMMAND_UI (ID_VIEW_SELMARGIN, OnUpdateSelMargin)
+ON_COMMAND (ID_VIEW_SELMARGIN, OnSelMargin)
+ON_UPDATE_COMMAND_UI (ID_VIEW_WORDWRAP, OnUpdateWordWrap)
+ON_COMMAND (ID_VIEW_WORDWRAP, OnWordWrap)
+ON_COMMAND (ID_FORCE_REDRAW, OnForceRedraw)
+       //BEGIN SW
+       // incremental search
+       ON_COMMAND(ID_EDIT_FIND_INCREMENTAL_FORWARD, OnEditFindIncrementalForward)
+       ON_COMMAND(ID_EDIT_FIND_INCREMENTAL_BACKWARD, OnEditFindIncrementalBackward)
+       ON_UPDATE_COMMAND_UI(ID_EDIT_FIND_INCREMENTAL_FORWARD, OnUpdateEditFindIncrementalForward)
+       ON_UPDATE_COMMAND_UI(ID_EDIT_FIND_INCREMENTAL_BACKWARD, OnUpdateEditFindIncrementalBackward)
+       //END SW
+END_MESSAGE_MAP ()
+
+#define EXPAND_PRIMITIVE(impl, func)    \
+void CCrystalTextView::On##func() { impl(FALSE); }  \
+void CCrystalTextView::OnExt##func() { impl(TRUE); }
+EXPAND_PRIMITIVE (MoveLeft, CharLeft)
+EXPAND_PRIMITIVE (MoveRight, CharRight)
+EXPAND_PRIMITIVE (MoveWordLeft, WordLeft)
+EXPAND_PRIMITIVE (MoveWordRight, WordRight)
+EXPAND_PRIMITIVE (MoveUp, LineUp)
+EXPAND_PRIMITIVE (MoveDown, LineDown)
+EXPAND_PRIMITIVE (MovePgUp, PageUp)
+EXPAND_PRIMITIVE (MovePgDn, PageDown)
+EXPAND_PRIMITIVE (MoveHome, Home)
+EXPAND_PRIMITIVE (MoveEnd, LineEnd)
+EXPAND_PRIMITIVE (MoveCtrlHome, TextBegin)
+EXPAND_PRIMITIVE (MoveCtrlEnd, TextEnd)
+#undef EXPAND_PRIMITIVE
+
+CCrystalTextView::TextDefinition CCrystalTextView::m_SourceDefs[] =
+  {
+    CCrystalTextView::SRC_PLAIN, _T ("Plain"), _T ("txt,doc,diz"), CCrystalTextView::ParseLinePlain, SRCOPT_AUTOINDENT, 4, _T (""), _T (""), _T (""), (DWORD)-1,
+    CCrystalTextView::SRC_ASP, _T ("ASP"), _T ("asp"), CCrystalTextView::ParseLineAsp, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T (""), _T (""), _T ("'"), (DWORD)-1,
+    CCrystalTextView::SRC_BASIC, _T ("Basic"), _T ("bas,vb,vbs,frm,dsm"), CCrystalTextView::ParseLineBasic, SRCOPT_AUTOINDENT, 4, _T (""), _T (""), _T ("\'"), (DWORD)-1,
+    CCrystalTextView::SRC_BATCH, _T ("Batch"), _T ("bat,btm,cmd"), CCrystalTextView::ParseLineBatch, SRCOPT_INSERTTABS|SRCOPT_AUTOINDENT, 4, _T (""), _T (""), _T ("rem "), (DWORD)-1,
+    CCrystalTextView::SRC_C, _T ("C"), _T ("c,cc,cpp,cxx,h,hpp.hxx,hm,inl,rh,tlh,tli,xs"), CCrystalTextView::ParseLineC, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_DCL, _T ("DCL"), _T ("dcl,dcc"), CCrystalTextView::ParseLineDcl, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_FORTRAN, _T ("Fortran"), _T ("f,f90,f9p,fpp"), CCrystalTextView::ParseLineFortran, SRCOPT_INSERTTABS|SRCOPT_AUTOINDENT, 8, _T (""), _T (""), _T ("!"), (DWORD)-1,
+    CCrystalTextView::SRC_HTML, _T ("HTML"), _T ("html,htm,shtml,ihtml,ssi"), CCrystalTextView::ParseLineHtml, SRCOPT_AUTOINDENT|SRCOPT_BRACEANSI, 2, _T ("<!--"), _T ("-->"), _T (""), (DWORD)-1,
+    CCrystalTextView::SRC_INSTALLSHIELD, _T ("InstallShield"), _T ("rul"), CCrystalTextView::ParseLineIS, SRCOPT_AUTOINDENT|SRCOPT_BRACEANSI, 2, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_JAVA, _T ("Java"), _T ("java,jav,js"), CCrystalTextView::ParseLineJava, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_LISP, _T ("AutoLISP"), _T ("lsp"), CCrystalTextView::ParseLineLisp, SRCOPT_AUTOINDENT|SRCOPT_BRACEANSI, 2, _T (";|"), _T ("|;"), _T (";"), (DWORD)-1,
+    CCrystalTextView::SRC_PASCAL, _T ("Pascal"), _T ("pas"), CCrystalTextView::ParseLinePascal, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T ("{"), _T ("}"), _T (""), (DWORD)-1,
+    CCrystalTextView::SRC_PERL, _T ("Perl"), _T ("pl"), CCrystalTextView::ParseLinePerl, SRCOPT_AUTOINDENT|SRCOPT_EOLNUNIX, 4, _T (""), _T (""), _T ("#"), (DWORD)-1,
+    CCrystalTextView::SRC_PHP, _T ("PHP"), _T ("php,php3,php4"), CCrystalTextView::ParseLinePhp, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_PYTHON, _T ("Python"), _T ("py"), CCrystalTextView::ParseLinePython, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_REXX, _T ("REXX"), _T ("rex,rexx,cmd"), CCrystalTextView::ParseLineRexx, SRCOPT_AUTOINDENT, 4, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_RSRC, _T ("Resources"), _T ("rc,dlg"), CCrystalTextView::ParseLineRsrc, SRCOPT_AUTOINDENT, 4, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_SGML, _T ("Sgml"), _T ("sgml"), CCrystalTextView::ParseLineSgml, SRCOPT_AUTOINDENT|SRCOPT_BRACEANSI, 2, _T ("<!--"), _T ("-->"), _T (""), (DWORD)-1,
+    CCrystalTextView::SRC_SH, _T ("Shell"), _T ("sh,conf"), CCrystalTextView::ParseLineSh, SRCOPT_INSERTTABS|SRCOPT_AUTOINDENT|SRCOPT_EOLNUNIX, 4, _T (""), _T (""), _T ("#"), (DWORD)-1,
+    CCrystalTextView::SRC_SIOD, _T ("SIOD"), _T ("scm"), CCrystalTextView::ParseLineSiod, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU, 2, _T (";|"), _T ("|;"), _T (";"), (DWORD)-1,
+    CCrystalTextView::SRC_SQL, _T ("SQL"), _T ("sql"), CCrystalTextView::ParseLineSql, SRCOPT_AUTOINDENT, 4, _T ("/*"), _T ("*/"), _T ("//"), (DWORD)-1,
+    CCrystalTextView::SRC_TCL, _T ("TCL"), _T ("tcl"), CCrystalTextView::ParseLineTcl, SRCOPT_AUTOINDENT|SRCOPT_BRACEGNU|SRCOPT_EOLNUNIX, 2, _T (""), _T (""), _T ("#"), (DWORD)-1,
+    CCrystalTextView::SRC_TEX, _T ("TEX"), _T ("tex,sty,cls,clo,ltx,fd,dtx"), CCrystalTextView::ParseLineTex, SRCOPT_AUTOINDENT, 4, _T (""), _T (""), _T ("%"), (DWORD)-1
+  };
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextView construction/destruction
+
+BOOL
+MatchType (CString pattern, LPCTSTR lpszExt)
+{
+  CString part;
+  int pos, len = pattern.GetLength ();
+
+  while ((pos = pattern.Find (_T (','))) != -1)
+    {
+      part = pattern.Left (pos);
+      if (!part.IsEmpty () && fpattern_isvalid (part))
+        {
+          if (fpattern_matchn (part, lpszExt))
+            {
+              return TRUE;
+            }
+        }
+      len -= pos + 1;
+      pattern = pattern.Right (len);
+    }
+  if (!pattern.IsEmpty () && fpattern_isvalid (pattern))
+    {
+      if (fpattern_matchn (pattern, lpszExt))
+        {
+          return TRUE;
+        }
+    }
+  return FALSE;
+}
+
+bool CCrystalTextView::
+DoSetTextType (TextDefinition *def)
+{
+  m_CurSourceDef = def;
+  SetFlags (def->flags);
+  SetWordWrapping ((def->flags & SRCOPT_WORDWRAP) != FALSE);
+  SetSelectionMargin ((def->flags & SRCOPT_SELMARGIN) != FALSE);
+  SetTabSize (def->tabsize);
+  SetViewTabs ((def->flags & SRCOPT_SHOWTABS) != FALSE);
+  int nEoln;
+  if (def->flags & SRCOPT_EOLNDOS)
+    {
+      nEoln = 0;
+    }
+  else if (def->flags & SRCOPT_EOLNUNIX)
+    {
+      nEoln = 1;
+    }
+  else if (def->flags & SRCOPT_EOLNMAC)
+    {
+      nEoln = 2;
+    }
+  else /* eoln auto */
+    {
+      nEoln = -1;
+    }
+  SetCRLFMode (nEoln);
+  return true;
+}
+
+CCrystalTextView::TextDefinition* CCrystalTextView::
+GetTextType (LPCTSTR pszExt)
+{
+  TextDefinition *def;
+  CString sExt = pszExt;
+
+  def = CCrystalTextView::m_SourceDefs;
+  sExt.MakeLower ();
+  for (int i = 0; i < countof (CCrystalTextView::m_SourceDefs); i++, def++)
+    if (MatchType (def->exts, sExt))
+      return def;
+  return NULL;
+}
+
+bool CCrystalTextView::
+SetTextType (LPCTSTR pszExt)
+{
+  m_CurSourceDef = m_SourceDefs;
+
+  TextDefinition *def = GetTextType (pszExt);
+
+  return SetTextType (def);
+}
+
+bool CCrystalTextView::
+SetTextType (CCrystalTextView::TextType enuType)
+{
+  TextDefinition *def;
+
+  m_CurSourceDef = def = m_SourceDefs;
+  for (int i = 0; i < countof (m_SourceDefs); i++, def++)
+    {
+      if (def->type == enuType)
+        {
+          return SetTextType (def);
+        }
+    }
+  return false;
+}
+
+bool CCrystalTextView::
+SetTextType (CCrystalTextView::TextDefinition *def)
+{
+  if (def)
+    if (m_CurSourceDef != def)
+      return DoSetTextType (def);
+    else
+      return true;
+  return false;
+}
+
+void CCrystalTextView::
+LoadSettings ()
+{
+  TextDefinition *def = m_SourceDefs;
+  bool bFontLoaded;
+  CReg reg;
+  if (reg.Open (HKEY_CURRENT_USER, REG_EDITPAD, KEY_READ))
+    {
+      reg.LoadNumber (_T ("DefaultEncoding"), (DWORD*) &CCrystalTextBuffer::m_nDefaultEncoding);
+      for (int i = 0; i < countof (m_SourceDefs); i++, def++)
+        {
+          CReg reg1;
+          if (reg1.Open (reg.hKey, def->name, KEY_READ))
+            {
+              reg1.LoadString (_T ("Extensions"), def->exts, countof (def->exts));
+              reg1.LoadNumber (_T ("Flags"), &def->flags);
+              reg1.LoadNumber (_T ("TabSize"), &def->tabsize);
+              reg1.LoadString (_T ("OpenComment"), def->opencomment, countof (def->opencomment));
+              reg1.LoadString (_T ("CloseComment"), def->closecomment, countof (def->closecomment));
+              reg1.LoadString (_T ("CommentLine"), def->commentline, countof (def->commentline));
+              reg1.LoadNumber (_T ("DefaultEncoding"), &def->encoding);
+            }
+        }
+      bFontLoaded = reg.LoadBinary (_T ("LogFont"), (LPBYTE) &m_LogFont, sizeof (m_LogFont));
+    }
+  else
+    bFontLoaded = false;
+  if (!bFontLoaded)
+    {
+      CWindowDC dc (CWnd::GetDesktopWindow ());
+      NONCLIENTMETRICS info;
+      info.cbSize = sizeof(info);
+      SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+      memcpy (&m_LogFont, &info.lfMessageFont, sizeof (LOGFONT));
+      m_LogFont.lfHeight = -MulDiv (11, dc.GetDeviceCaps (LOGPIXELSY), 72);
+      m_LogFont.lfWeight = FW_NORMAL;
+      m_LogFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+      m_LogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+      m_LogFont.lfQuality = DEFAULT_QUALITY;
+      m_LogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+      _tcscpy (m_LogFont.lfFaceName, _T ("Courier New"));
+    }
+}
+
+void CCrystalTextView::
+SaveSettings ()
+{
+  TextDefinition *def = m_SourceDefs;
+  CReg reg;
+  if (reg.Create (HKEY_CURRENT_USER, REG_EDITPAD, KEY_WRITE))
+    {
+      VERIFY (reg.SaveNumber (_T ("DefaultEncoding"), (DWORD) CCrystalTextBuffer::m_nDefaultEncoding));
+      for (int i = 0; i < countof (m_SourceDefs); i++, def++)
+        {
+          CReg reg1;
+          if (reg1.Create (reg.hKey, def->name, KEY_WRITE))
+            {
+              VERIFY (reg1.SaveString (_T ("Extensions"), def->exts));
+              VERIFY (reg1.SaveNumber (_T ("Flags"), def->flags));
+              VERIFY (reg1.SaveNumber (_T ("TabSize"), def->tabsize));
+              VERIFY (reg1.SaveString (_T ("OpenComment"), def->opencomment));
+              VERIFY (reg1.SaveString (_T ("CloseComment"), def->closecomment));
+              VERIFY (reg1.SaveString (_T ("CommentLine"), def->commentline));
+              VERIFY (reg1.SaveNumber (_T ("DefaultEncoding"), def->encoding));
+            }
+        }
+      VERIFY (reg.SaveBinary (_T ("LogFont"), (LPBYTE) &m_LogFont, sizeof (m_LogFont)));
+    }
+}
+
+CCrystalTextView::CCrystalTextView ()
+{
+  AFX_ZERO_INIT_OBJECT (CView);
+  m_rxnode = NULL;
+  m_pszMatched = NULL;
+  m_bSelMargin = TRUE;
+  m_bWordWrap = FALSE;
+       //BEGIN SW
+       m_panSubLines = new CArray<int, int>();
+       ASSERT( m_panSubLines );
+       m_panSubLines->SetSize( 0, 4096 );
+
+       m_pstrIncrementalSearchString = new CString;
+       ASSERT( m_pstrIncrementalSearchString );
+       m_pstrIncrementalSearchStringOld = new CString;
+       ASSERT( m_pstrIncrementalSearchStringOld );
+       //END SW
+  ResetView ();
+  SetTextType (SRC_PLAIN);
+  m_bSingle = false; // needed to be set in descendat classes
+  m_bRememberLastPos = false;
+}
+
+CCrystalTextView::~CCrystalTextView ()
+{
+       ASSERT (m_hAccel == NULL);
+       ASSERT (m_pCacheBitmap == NULL);
+       ASSERT (m_pTextBuffer == NULL);   //  Must be correctly detached
+       
+       if (m_pszLastFindWhat != NULL)
+       {
+               free (m_pszLastFindWhat);
+               m_pszLastFindWhat=NULL;
+       }
+       if (m_pdwParseCookies != NULL)
+       {
+               delete m_pdwParseCookies;
+               m_pdwParseCookies = NULL;
+       }
+       if (m_pnActualLineLength != NULL)
+       {
+               delete m_pnActualLineLength;
+               m_pnActualLineLength = NULL;
+       }
+       if (m_rxnode)
+       {
+               RxFree (m_rxnode);
+               m_rxnode = NULL;
+       }
+       if (m_pszMatched)
+       {
+               delete m_pszMatched;
+               m_pszMatched = NULL;
+       }
+       //BEGIN SW
+       if( m_panSubLines )
+       {
+               delete m_panSubLines;
+               m_panSubLines = NULL;
+       }
+       if( m_pstrIncrementalSearchString )
+       {
+               delete m_pstrIncrementalSearchString;
+               m_pstrIncrementalSearchString = NULL;
+       }
+       if( m_pstrIncrementalSearchStringOld )
+       {
+               delete m_pstrIncrementalSearchStringOld;
+               m_pstrIncrementalSearchStringOld = NULL;
+       }
+       //END SW
+}
+
+BOOL CCrystalTextView::
+PreCreateWindow (CREATESTRUCT & cs)
+{
+  CWnd *pParentWnd = CWnd::FromHandlePermanent (cs.hwndParent);
+  if (pParentWnd == NULL || !pParentWnd->IsKindOf (RUNTIME_CLASS (CSplitterWnd)))
+    {
+      //  View must always create its own scrollbars,
+      //  if only it's not used within splitter
+               //BEGIN SW
+               if( m_bWordWrap )
+                       // we do not need a horizontal scroll bar, if we wrap the lines
+                       cs.style|= WS_VSCROLL;
+               else
+                       cs.style |= (WS_HSCROLL | WS_VSCROLL);
+               /*ORIGINAL
+               cs.style |= (WS_HSCROLL | WS_VSCROLL);
+               */
+               //END SW
+    }
+  cs.lpszClass = AfxRegisterWndClass (CS_DBLCLKS);
+  return CView::PreCreateWindow (cs);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextView drawing
+
+void CCrystalTextView::
+GetSelection (CPoint & ptStart, CPoint & ptEnd)
+{
+  PrepareSelBounds ();
+  ptStart = m_ptDrawSelStart;
+  ptEnd = m_ptDrawSelEnd;
+}
+
+CCrystalTextBuffer *CCrystalTextView::
+LocateTextBuffer ()
+{
+  return NULL;
+}
+
+int CCrystalTextView::
+GetLineActualLength (int nLineIndex)
+{
+  int nLineCount = GetLineCount ();
+  ASSERT (nLineCount > 0);
+  ASSERT (nLineIndex >= 0 && nLineIndex < nLineCount);
+  if (m_pnActualLineLength == NULL)
+    {
+      m_pnActualLineLength = new int[nLineCount];
+      memset (m_pnActualLineLength, 0xff, sizeof (int) * nLineCount);
+      m_nActualLengthArraySize = nLineCount;
+    }
+
+  if (m_pnActualLineLength[nLineIndex] >= 0)
+    return m_pnActualLineLength[nLineIndex];
+
+  //  Actual line length is not determined yet, let's calculate a little
+  int nActualLength = 0;
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength > 0)
+    {
+      LPCTSTR pszLine = GetLineChars (nLineIndex);
+      LPTSTR pszChars = (LPTSTR) _alloca (sizeof (TCHAR) * (nLength + 1));
+      memcpy (pszChars, pszLine, sizeof (TCHAR) * nLength);
+      pszChars[nLength] = 0;
+      LPTSTR pszCurrent = pszChars;
+
+      int nTabSize = GetTabSize ();
+      for (;;)
+        {
+          LPTSTR psz = _tcschr (pszCurrent, _T('\t'));
+          if (psz == NULL)
+            {
+              nActualLength += (pszChars + nLength - pszCurrent);
+              break;
+            }
+
+          nActualLength += (psz - pszCurrent);
+          nActualLength += (nTabSize - nActualLength % nTabSize);
+          pszCurrent = psz + 1;
+        }
+    }
+
+  m_pnActualLineLength[nLineIndex] = nActualLength;
+  return nActualLength;
+}
+
+void CCrystalTextView::
+ScrollToChar (int nNewOffsetChar, BOOL bNoSmoothScroll /*= FALSE*/ , BOOL bTrackScrollBar /*= TRUE*/ )
+{
+       //BEGIN SW
+       // no horizontal scrolling, when word wrapping is enabled
+       if( m_bWordWrap )
+               return;
+       //END SW
+       
+  //  For now, ignoring bNoSmoothScroll and m_bSmoothScroll
+  if (m_nOffsetChar != nNewOffsetChar)
+    {
+      int nScrollChars = m_nOffsetChar - nNewOffsetChar;
+      m_nOffsetChar = nNewOffsetChar;
+      CRect rcScroll;
+      GetClientRect (&rcScroll);
+      rcScroll.left += GetMarginWidth ();
+      ScrollWindow (nScrollChars * GetCharWidth (), 0, &rcScroll, &rcScroll);
+      UpdateWindow ();
+      if (bTrackScrollBar)
+        RecalcHorzScrollBar (TRUE);
+    }
+}
+
+//BEGIN SW
+void CCrystalTextView::ScrollToSubLine( int nNewTopSubLine, 
+                                                                       BOOL bNoSmoothScroll /*= FALSE*/, BOOL bTrackScrollBar /*= TRUE*/ )
+{
+       if (m_nTopSubLine != nNewTopSubLine)
+       {
+               if (bNoSmoothScroll || ! m_bSmoothScroll)
+               {
+                       int nScrollLines = m_nTopSubLine - nNewTopSubLine;
+                       m_nTopSubLine = nNewTopSubLine;
+                       ScrollWindow(0, nScrollLines * GetLineHeight());
+                       UpdateWindow();
+                       if (bTrackScrollBar)
+                               RecalcVertScrollBar(TRUE);
+               }
+               else
+               {
+                       //      Do smooth scrolling
+                       int nLineHeight = GetLineHeight();
+                       if (m_nTopSubLine > nNewTopSubLine)
+                       {
+                               int nIncrement = (m_nTopSubLine - nNewTopSubLine) / SMOOTH_SCROLL_FACTOR + 1;
+                               while (m_nTopSubLine != nNewTopSubLine)
+                               {
+                                       int nTopSubLine = m_nTopSubLine - nIncrement;
+                                       if (nTopSubLine < nNewTopSubLine)
+                                               nTopSubLine = nNewTopSubLine;
+                                       int nScrollLines = nTopSubLine - m_nTopSubLine;
+                                       m_nTopSubLine = nTopSubLine;
+                                       ScrollWindow(0, - nLineHeight * nScrollLines);
+                                       UpdateWindow();
+                                       if (bTrackScrollBar)
+                                               RecalcVertScrollBar(TRUE);
+                               }
+                       }
+                       else
+                       {
+                               int nIncrement = (nNewTopSubLine - m_nTopSubLine) / SMOOTH_SCROLL_FACTOR + 1;
+                               while (m_nTopSubLine != nNewTopSubLine)
+                               {
+                                       int nTopSubLine = m_nTopSubLine + nIncrement;
+                                       if (nTopSubLine > nNewTopSubLine)
+                                               nTopSubLine = nNewTopSubLine;
+                                       int nScrollLines = nTopSubLine - m_nTopSubLine;
+                                       m_nTopSubLine = nTopSubLine;
+                                       ScrollWindow(0, - nLineHeight * nScrollLines);
+                                       UpdateWindow();
+                                       if (bTrackScrollBar)
+                                               RecalcVertScrollBar(TRUE);
+                               }
+                       }
+               }
+               int nDummy;
+               GetLineBySubLine( m_nTopSubLine, m_nTopLine, nDummy );
+               InvalidateRect( NULL ); // repaint whole window
+       }
+}
+
+/*void CCrystalTextView::GoToLine( int nLine )
+{
+       SetCursorPos( CPoint( 0, (nLine > 0)? nLine - 1 : 0 ) );
+       EnsureVisible( GetCursorPos() );
+}*/
+//END SW
+
+void CCrystalTextView::
+ScrollToLine (int nNewTopLine, BOOL bNoSmoothScroll /*= FALSE*/ , BOOL bTrackScrollBar /*= TRUE*/ )
+{
+       //BEGIN SW
+       if( m_nTopLine != nNewTopLine )
+               ScrollToSubLine( GetSubLineIndex( nNewTopLine ), bNoSmoothScroll, bTrackScrollBar );
+
+       /*ORIGINAL
+       if (m_nTopLine != nNewTopLine)
+       {
+               if (bNoSmoothScroll || ! m_bSmoothScroll)
+               {
+                       int nScrollLines = m_nTopLine - nNewTopLine;
+                       m_nTopLine = nNewTopLine;
+                       ScrollWindow(0, nScrollLines * GetLineHeight());
+                       UpdateWindow();
+                       if (bTrackScrollBar)
+                               RecalcVertScrollBar(TRUE);
+               }
+               else
+               {
+                       //      Do smooth scrolling
+                       int nLineHeight = GetLineHeight();
+                       if (m_nTopLine > nNewTopLine)
+                       {
+                               int nIncrement = (m_nTopLine - nNewTopLine) / SMOOTH_SCROLL_FACTOR + 1;
+                               while (m_nTopLine != nNewTopLine)
+                               {
+                                       int nTopLine = m_nTopLine - nIncrement;
+                                       if (nTopLine < nNewTopLine)
+                                               nTopLine = nNewTopLine;
+                                       int nScrollLines = nTopLine - m_nTopLine;
+                                       m_nTopLine = nTopLine;
+                                       ScrollWindow(0, - nLineHeight * nScrollLines);
+                                       UpdateWindow();
+                                       if (bTrackScrollBar)
+                                               RecalcVertScrollBar(TRUE);
+                               }
+                       }
+                       else
+                       {
+                               int nIncrement = (nNewTopLine - m_nTopLine) / SMOOTH_SCROLL_FACTOR + 1;
+                               while (m_nTopLine != nNewTopLine)
+                               {
+                                       int nTopLine = m_nTopLine + nIncrement;
+                                       if (nTopLine > nNewTopLine)
+                                               nTopLine = nNewTopLine;
+                                       int nScrollLines = nTopLine - m_nTopLine;
+                                       m_nTopLine = nTopLine;
+                                       ScrollWindow(0, - nLineHeight * nScrollLines);
+                                       UpdateWindow();
+                                       if (bTrackScrollBar)
+                                               RecalcVertScrollBar(TRUE);
+                               }
+                       }
+               }
+       }
+       *///END SW
+}
+
+void CCrystalTextView::
+ExpandChars (LPCTSTR pszChars, int nOffset, int nCount, CString & line)
+{
+  if (nCount <= 0)
+    {
+      line = _T ("");
+      return;
+    }
+
+  int nTabSize = GetTabSize ();
+
+  int nActualOffset = 0;
+  for (int I = 0; I < nOffset; I++)
+    {
+      if (pszChars[I] == _T ('\t'))
+        nActualOffset += (nTabSize - nActualOffset % nTabSize);
+      else
+        nActualOffset++;
+    }
+
+  pszChars += nOffset;
+  int nLength = nCount;
+
+  int nTabCount = 0;
+  for (I = 0; I < nLength; I++)
+    {
+      if (pszChars[I] == _T ('\t'))
+        nTabCount++;
+    }
+
+  LPTSTR pszBuf = line.GetBuffer (nLength + nTabCount * (nTabSize - 1) + 1);
+  int nCurPos = 0;
+  if (nTabCount > 0 || m_bViewTabs)
+    {
+      for (I = 0; I < nLength; I++)
+        {
+          if (pszChars[I] == _T ('\t'))
+            {
+              int nSpaces = nTabSize - (nActualOffset + nCurPos) % nTabSize;
+              if (m_bViewTabs)
+                {
+                  pszBuf[nCurPos++] = TAB_CHARACTER;
+                  nSpaces--;
+                }
+              while (nSpaces > 0)
+                {
+                  pszBuf[nCurPos++] = _T (' ');
+                  nSpaces--;
+                }
+            }
+          else
+            {
+              if (pszChars[I] == _T (' ') && m_bViewTabs)
+                pszBuf[nCurPos] = SPACE_CHARACTER;
+              else
+                pszBuf[nCurPos] = pszChars[I];
+              nCurPos++;
+            }
+        }
+    }
+  else
+    {
+      memcpy (pszBuf, pszChars, sizeof (TCHAR) * nLength);
+      nCurPos = nLength;
+    }
+  pszBuf[nCurPos] = 0;
+  line.ReleaseBuffer ();
+}
+
+void CCrystalTextView::
+DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
+                    LPCTSTR pszChars, int nOffset, int nCount)
+{
+  ASSERT (nCount >= 0);
+  if (nCount > 0)
+    {
+      CString line;
+      ExpandChars (pszChars, nOffset, nCount, line);
+      int nWidth = rcClip.right - ptOrigin.x;
+      if (nWidth > 0)
+        {
+          int nCharWidth = GetCharWidth ();
+          int nCount = line.GetLength ();
+          int nCountFit = nWidth / nCharWidth + 1;
+          if (nCount > nCountFit)
+            nCount = nCountFit;
+#ifdef _DEBUG
+          //CSize sz = pdc->GetTextExtent(line, nCount);
+          //ASSERT(sz.cx == m_nCharWidth * nCount);
+#endif
+          /*
+             CRect rcBounds = rcClip;
+             rcBounds.left = ptOrigin.x;
+             rcBounds.right = rcBounds.left + GetCharWidth() * nCount;
+             pdc->ExtTextOut(rcBounds.left, rcBounds.top, ETO_OPAQUE, &rcBounds, NULL, 0, NULL);
+           */
+          VERIFY (pdc->ExtTextOut (ptOrigin.x, ptOrigin.y, ETO_CLIPPED, &rcClip, line, nCount, NULL));
+        }
+      ptOrigin.x += GetCharWidth () * line.GetLength ();
+    }
+}
+
+void CCrystalTextView::
+DrawLineHelper (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip, int nColorIndex,
+                LPCTSTR pszChars, int nOffset, int nCount, CPoint ptTextPos)
+{
+  if (nCount > 0)
+    {
+      if (m_bFocused || m_bShowInactiveSelection)
+        {
+          int nSelBegin = 0, nSelEnd = 0;
+          if (m_ptDrawSelStart.y > ptTextPos.y)
+            {
+              nSelBegin = nCount;
+            }
+          else if (m_ptDrawSelStart.y == ptTextPos.y)
+            {
+              nSelBegin = m_ptDrawSelStart.x - ptTextPos.x;
+              if (nSelBegin < 0)
+                nSelBegin = 0;
+              if (nSelBegin > nCount)
+                nSelBegin = nCount;
+            }
+          if (m_ptDrawSelEnd.y > ptTextPos.y)
+            {
+              nSelEnd = nCount;
+            }
+          else if (m_ptDrawSelEnd.y == ptTextPos.y)
+            {
+              nSelEnd = m_ptDrawSelEnd.x - ptTextPos.x;
+              if (nSelEnd < 0)
+                nSelEnd = 0;
+              if (nSelEnd > nCount)
+                nSelEnd = nCount;
+            }
+
+          ASSERT (nSelBegin >= 0 && nSelBegin <= nCount);
+          ASSERT (nSelEnd >= 0 && nSelEnd <= nCount);
+          ASSERT (nSelBegin <= nSelEnd);
+
+          //  Draw part of the text before selection
+          if (nSelBegin > 0)
+            {
+              DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset, nSelBegin);
+            }
+          if (nSelBegin < nSelEnd)
+            {
+              COLORREF crOldBk = pdc->SetBkColor (GetColor (COLORINDEX_SELBKGND));
+              COLORREF crOldText = pdc->SetTextColor (GetColor (COLORINDEX_SELTEXT));
+              DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset + nSelBegin, nSelEnd - nSelBegin);
+              pdc->SetBkColor (crOldBk);
+              pdc->SetTextColor (crOldText);
+            }
+          if (nSelEnd < nCount)
+            {
+              DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset + nSelEnd, nCount - nSelEnd);
+            }
+        }
+      else
+        {
+          DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset, nCount);
+        }
+    }
+}
+
+void CCrystalTextView::
+GetLineColors (int nLineIndex, COLORREF & crBkgnd,
+               COLORREF & crText, BOOL & bDrawWhitespace)
+{
+  DWORD dwLineFlags = GetLineFlags (nLineIndex);
+  bDrawWhitespace = TRUE;
+  crText = RGB (255, 255, 255);
+  if (dwLineFlags & LF_EXECUTION)
+    {
+      crBkgnd = RGB (0, 128, 0);
+      return;
+    }
+  if (dwLineFlags & LF_BREAKPOINT)
+    {
+      crBkgnd = RGB (255, 0, 0);
+      return;
+    }
+  if (dwLineFlags & LF_INVALID_BREAKPOINT)
+    {
+      crBkgnd = RGB (128, 128, 0);
+      return;
+    }
+  if (dwLineFlags & LF_DIFF)
+    {
+      crBkgnd = RGB(255,255,92);
+      return;
+    }
+  if (dwLineFlags & LF_DELETED)
+    {
+      crBkgnd = RGB(192,192,192);
+      return;
+    }
+  crBkgnd = CLR_NONE;
+  crText = CLR_NONE;
+  bDrawWhitespace = FALSE;
+}
+
+DWORD CCrystalTextView::
+GetParseCookie (int nLineIndex)
+{
+  int nLineCount = GetLineCount ();
+  if (m_pdwParseCookies == NULL)
+    {
+      m_nParseArraySize = nLineCount;
+      m_pdwParseCookies = new DWORD[nLineCount];
+      memset (m_pdwParseCookies, 0xff, nLineCount * sizeof (DWORD));
+    }
+
+  if (nLineIndex < 0)
+    return 0;
+  if (m_pdwParseCookies[nLineIndex] != (DWORD) - 1)
+    return m_pdwParseCookies[nLineIndex];
+
+  int L = nLineIndex;
+  while (L >= 0 && m_pdwParseCookies[L] == (DWORD) - 1)
+    L--;
+  L++;
+
+  int nBlocks;
+  while (L <= nLineIndex)
+    {
+      DWORD dwCookie = 0;
+      if (L > 0)
+        dwCookie = m_pdwParseCookies[L - 1];
+      ASSERT (dwCookie != (DWORD) - 1);
+      m_pdwParseCookies[L] = ParseLine (dwCookie, L, NULL, nBlocks);
+      ASSERT (m_pdwParseCookies[L] != (DWORD) - 1);
+      L++;
+    }
+
+  return m_pdwParseCookies[nLineIndex];
+}
+
+//BEGIN SW
+void CCrystalTextView::WrapLine( int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks )
+{
+       // There must be a parser attached to this view
+       if( !m_pParser )
+               return;
+
+       m_pParser->WrapLine( nLineIndex, nMaxLineWidth, anBreaks, nBreaks );
+}
+
+
+void CCrystalTextView::WrapLineCached( 
+                                                                               int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks )
+{
+       // if word wrap is not active, there is not any break in the line
+       if( !m_bWordWrap )
+       {
+               nBreaks = 0;
+               return;
+       }
+
+       // word wrap is active
+       if( nLineIndex < m_panSubLines->GetSize() && !anBreaks && (*m_panSubLines)[nLineIndex] > -1 )
+               // return cached data
+               nBreaks = (*m_panSubLines)[nLineIndex] - 1;
+       else
+       {
+               // recompute line wrap
+               nBreaks = 0;
+               WrapLine( nLineIndex, nMaxLineWidth, anBreaks, nBreaks );
+
+               // cache data
+               ASSERT( nBreaks > -1 );
+               m_panSubLines->SetAtGrow( nLineIndex, nBreaks + 1 );
+
+               // RecalcVertScrollBar();
+       }
+}
+
+
+void CCrystalTextView::InvalidateLineCache( int nLineIndex1, int nLineIndex2 /*= -1*/ )
+{
+       // invalidate cached sub line count
+
+       if( nLineIndex2 == -1 && nLineIndex1 < m_panSubLines->GetSize() )
+               for( int i = nLineIndex1; i < m_panSubLines->GetSize(); i++ )
+                       (*m_panSubLines)[i] = -1;
+       else
+       {
+               if( nLineIndex1 > nLineIndex2 )
+               {
+                       int     nStorage = nLineIndex1;
+                       nLineIndex1 = nLineIndex2;
+                       nLineIndex2 = nStorage;
+               }
+
+               if( nLineIndex1 >= m_panSubLines->GetSize() )
+                       return;
+
+               if( nLineIndex2 >= m_panSubLines->GetSize() )
+                       nLineIndex2 = m_panSubLines->GetUpperBound();
+
+               for( int i = nLineIndex1; i <= nLineIndex2; i++ )
+                       if( i >= 0 && i < m_panSubLines->GetSize() )
+                               (*m_panSubLines)[i] = -1;
+       }
+}
+
+
+void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &rcClip,
+                                                                                                                                                       TEXTBLOCK *pBuf, int nBlocks, int &nActualItem, 
+                                                                                                                                                       COLORREF crText, COLORREF crBkgnd, BOOL bDrawWhitespace,
+                                                                                                                                                       LPCTSTR pszChars, 
+                                                                                                                                                       int nOffset, int nCount, CPoint ptTextPos )
+{
+       CPoint  originalOrigin = ptOrigin;
+       CRect           frect = rcClip;
+       int                     nLength = GetLineLength( ptTextPos.y );
+
+       frect.top = ptOrigin.y;
+       frect.bottom = frect.top + GetLineHeight();
+
+       ASSERT( nActualItem < nBlocks );
+
+       if (crText == CLR_NONE)
+               pdc->SetTextColor(GetColor(pBuf[nActualItem].m_nColorIndex));
+       pdc->SelectObject(
+               GetFont(GetItalic(pBuf[nActualItem].m_nColorIndex), 
+               GetBold(pBuf[nActualItem].m_nColorIndex)));
+
+       if( nBlocks > 0 && nActualItem < nBlocks - 1 && 
+               pBuf[nActualItem + 1].m_nCharPos >= nOffset && 
+               pBuf[nActualItem + 1].m_nCharPos <= nOffset + nCount )
+       {
+               ASSERT(pBuf[nActualItem].m_nCharPos >= 0 && pBuf[nActualItem].m_nCharPos <= nLength);
+
+               /*
+               pdc->SelectObject(GetFont(GetItalic(COLORINDEX_NORMALTEXT), GetBold(COLORINDEX_NORMALTEXT)));
+               DrawLineHelper(
+                       pdc, ptOrigin, rcClip, pBuf[nActualItem].m_nColorIndex, pszChars, 
+                       nOffset, pBuf[nActualItem].m_nCharPos, ptTextPos);
+               */
+               for (int I = nActualItem; I < nBlocks - 1 && pBuf[I + 1].m_nCharPos <= nOffset + nCount; I ++)
+               {
+                       ASSERT(pBuf[I].m_nCharPos >= 0 && pBuf[I].m_nCharPos <= nLength);
+                       if (crText == CLR_NONE)
+                               pdc->SetTextColor(GetColor(pBuf[I].m_nColorIndex));
+
+                       pdc->SelectObject(GetFont(GetItalic(pBuf[I].m_nColorIndex), GetBold(pBuf[I].m_nColorIndex)));
+
+                       int nOffsetToUse = (nOffset > pBuf[I].m_nCharPos)? nOffset : pBuf[I].m_nCharPos;
+                       DrawLineHelper(pdc, ptOrigin, rcClip, pBuf[I].m_nColorIndex, pszChars,
+                                       (nOffset > pBuf[I].m_nCharPos)? nOffset : pBuf[I].m_nCharPos, 
+                                       pBuf[I + 1].m_nCharPos - nOffsetToUse,
+                                       CPoint( nOffsetToUse, ptTextPos.y ));
+               }
+
+               nActualItem = I;
+
+               ASSERT(pBuf[nActualItem].m_nCharPos >= 0 && pBuf[nActualItem].m_nCharPos <= nLength);
+               if (crText == CLR_NONE)
+                       pdc->SetTextColor(GetColor(pBuf[nActualItem].m_nColorIndex));
+
+               pdc->SelectObject(GetFont(GetItalic(pBuf[nActualItem].m_nColorIndex),
+                                                       GetBold(pBuf[nActualItem].m_nColorIndex)));
+               DrawLineHelper(pdc, ptOrigin, rcClip, pBuf[nActualItem].m_nColorIndex, pszChars,
+                                                       pBuf[nActualItem].m_nCharPos, nOffset + nCount - pBuf[nActualItem].m_nCharPos,
+                                                       CPoint(pBuf[nActualItem].m_nCharPos, ptTextPos.y));
+       }
+       else
+       {
+               DrawLineHelper(
+                       pdc, ptOrigin, rcClip, pBuf[nActualItem].m_nColorIndex, 
+                       pszChars, nOffset, nCount, ptTextPos);
+       }
+
+       // Draw space on the right of the text
+       if (ptOrigin.x > frect.left)
+               frect.left = ptOrigin.x;
+       if (frect.right > frect.left)
+       {
+               if ((m_bFocused || m_bShowInactiveSelection) 
+                       && IsInsideSelBlock(CPoint(GetLineLength( ptTextPos.y ), ptTextPos.y)) 
+                       && (nOffset + nCount) == GetLineLength( ptTextPos.y ) )
+               {
+                       pdc->FillSolidRect(frect.left, frect.top, GetCharWidth(), frect.Height(),
+                                                                                               GetColor(COLORINDEX_SELBKGND));
+                       frect.left += GetCharWidth();
+               }
+               if (frect.right > frect.left)
+                       pdc->FillSolidRect(frect, bDrawWhitespace ? crBkgnd : GetColor(COLORINDEX_WHITESPACE));
+       }
+
+       // set origin to beginning of next screen line
+       ptOrigin.x = originalOrigin.x;
+       ptOrigin.y+= GetLineHeight();
+}
+//END SW
+
+void CCrystalTextView::
+DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
+{
+  ASSERT (nLineIndex >= -1 && nLineIndex < GetLineCount ());
+
+  if (nLineIndex == -1)
+    {
+      //  Draw line beyond the text
+      pdc->FillSolidRect (rc, GetColor (COLORINDEX_WHITESPACE));
+      return;
+    }
+
+  //  Acquire the background color for the current line
+  BOOL bDrawWhitespace = FALSE;
+  COLORREF crBkgnd, crText;
+  GetLineColors (nLineIndex, crBkgnd, crText, bDrawWhitespace);
+  if (crBkgnd == CLR_NONE)
+    crBkgnd = GetColor (COLORINDEX_BKGND);
+
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength == 0)
+    {
+      //  Draw the empty line
+      CRect rect = rc;
+      if ((m_bFocused || m_bShowInactiveSelection) && IsInsideSelBlock (CPoint (0, nLineIndex)))
+        {
+          pdc->FillSolidRect (rect.left, rect.top, GetCharWidth (), rect.Height (), GetColor (COLORINDEX_SELBKGND));
+          rect.left += GetCharWidth ();
+        }
+      pdc->FillSolidRect (rect, bDrawWhitespace ? crBkgnd : GetColor (COLORINDEX_WHITESPACE));
+      return;
+    }
+
+  //  Parse the line
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  DWORD dwCookie = GetParseCookie (nLineIndex - 1);
+  TEXTBLOCK *pBuf = (TEXTBLOCK *) _alloca (sizeof (TEXTBLOCK) * nLength * 3);
+  int nBlocks = 0;
+       //BEGIN SW
+       // insert at least one textblock of normal color at the beginning
+       pBuf[0].m_nCharPos = 0;
+       pBuf[0].m_nColorIndex = COLORINDEX_NORMALTEXT;
+       nBlocks++;
+       //END SW
+  m_pdwParseCookies[nLineIndex] = ParseLine (dwCookie, nLineIndex, pBuf, nBlocks);
+  ASSERT (m_pdwParseCookies[nLineIndex] != (DWORD) - 1);
+
+       //BEGIN SW
+       int nActualItem = 0;
+
+       // Wrap the line
+       int *anBreaks = (int*)_alloca( sizeof( int ) * nLength );
+       int     nBreaks = 0;
+
+       WrapLineCached( nLineIndex, GetScreenChars(), anBreaks, nBreaks );
+       //END SW
+
+  //  Draw the line text
+  CPoint origin (rc.left - m_nOffsetChar * GetCharWidth (), rc.top);
+  pdc->SetBkColor (crBkgnd);
+  if (crText != CLR_NONE)
+    pdc->SetTextColor (crText);
+       BOOL bColorSet = FALSE;
+
+       //BEGIN SW
+       /*ORIGINAL
+       if (nBlocks > 0)
+       {
+               ASSERT(pBuf[0].m_nCharPos >= 0 && pBuf[0].m_nCharPos <= nLength);
+               if (crText == CLR_NONE)
+                       pdc->SetTextColor(GetColor(COLORINDEX_NORMALTEXT));
+               pdc->SelectObject(GetFont(GetItalic(COLORINDEX_NORMALTEXT), GetBold(COLORINDEX_NORMALTEXT)));
+               DrawLineHelper(pdc, origin, rc, COLORINDEX_NORMALTEXT, pszChars, 0, pBuf[0].m_nCharPos, CPoint(0, nLineIndex));
+               for (int I = 0; I < nBlocks - 1; I ++)
+               {
+                       ASSERT(pBuf[I].m_nCharPos >= 0 && pBuf[I].m_nCharPos <= nLength);
+                       if (crText == CLR_NONE)
+                               pdc->SetTextColor(GetColor(pBuf[I].m_nColorIndex));
+                       pdc->SelectObject(GetFont(GetItalic(pBuf[I].m_nColorIndex), GetBold(pBuf[I].m_nColorIndex)));
+                       DrawLineHelper(pdc, origin, rc, pBuf[I].m_nColorIndex, pszChars,
+                                                       pBuf[I].m_nCharPos, pBuf[I + 1].m_nCharPos - pBuf[I].m_nCharPos,
+                                                       CPoint(pBuf[I].m_nCharPos, nLineIndex));
+               }
+               ASSERT(pBuf[nBlocks - 1].m_nCharPos >= 0 && pBuf[nBlocks - 1].m_nCharPos <= nLength);
+               if (crText == CLR_NONE)
+                       pdc->SetTextColor(GetColor(pBuf[nBlocks - 1].m_nColorIndex));
+               pdc->SelectObject(GetFont(GetItalic(pBuf[nBlocks - 1].m_nColorIndex),
+                                                       GetBold(pBuf[nBlocks - 1].m_nColorIndex)));
+               DrawLineHelper(pdc, origin, rc, pBuf[nBlocks - 1].m_nColorIndex, pszChars,
+                                                       pBuf[nBlocks - 1].m_nCharPos, nLength - pBuf[nBlocks - 1].m_nCharPos,
+                                                       CPoint(pBuf[nBlocks - 1].m_nCharPos, nLineIndex));
+       }
+       else
+       */
+       //END SW
+
+       // BEGIN SW
+       if( nBreaks > 0 )
+       {
+               // Draw all the screen lines of the wrapped line
+               ASSERT( anBreaks[0] < nLength );
+               
+               // draw start of line to first break
+               DrawScreenLine(
+                       pdc, origin, rc,
+                       pBuf, nBlocks, nActualItem,
+                       crText, crBkgnd, bDrawWhitespace,
+                       pszChars, 0, anBreaks[0], CPoint( 0, nLineIndex ) );
+               
+               // draw from first break to last break
+               for( int i = 0; i < nBreaks - 1; i++ )
+               {
+                       ASSERT( anBreaks[i] >= 0 && anBreaks[i] < nLength );
+                       DrawScreenLine(
+                               pdc, origin, rc,
+                               pBuf, nBlocks, nActualItem,
+                               crText, crBkgnd, bDrawWhitespace,
+                               pszChars, anBreaks[i], anBreaks[i + 1] - anBreaks[i],
+                               CPoint( anBreaks[i], nLineIndex ) );
+               }
+               
+               // draw from last break till end of line
+               DrawScreenLine(
+                       pdc, origin, rc,
+                       pBuf, nBlocks, nActualItem,
+                       crText, crBkgnd, bDrawWhitespace,
+                       pszChars, anBreaks[i], nLength - anBreaks[i],
+                       CPoint( anBreaks[i], nLineIndex ) );
+       }
+       else
+               DrawScreenLine(
+               pdc, origin, rc,
+               pBuf, nBlocks, nActualItem,
+               crText, crBkgnd, bDrawWhitespace,
+               pszChars, 0, nLength, CPoint(0, nLineIndex));
+
+       //      Draw whitespaces to the left of the text
+       //BEGIN SW
+       // Drawing is now realized by DrawScreenLine()
+       /*ORIGINAL
+       CRect frect = rc;
+       if (origin.x > frect.left)
+               frect.left = origin.x;
+       if (frect.right > frect.left)
+       {
+               if ((m_bFocused || m_bShowInactiveSelection) && IsInsideSelBlock(CPoint(nLength, nLineIndex)))
+               {
+                       pdc->FillSolidRect(frect.left, frect.top, GetCharWidth(), frect.Height(),
+                                                                                               GetColor(COLORINDEX_SELBKGND));
+                       frect.left += GetCharWidth();
+               }
+               if (frect.right > frect.left)
+                       pdc->FillSolidRect(frect, bDrawWhitespace ? crBkgnd : GetColor(COLORINDEX_WHITESPACE));
+       }
+       */
+       //END SW
+}
+
+COLORREF CCrystalTextView::
+GetColor (int nColorIndex)
+{
+  switch (nColorIndex)
+    {
+    case COLORINDEX_WHITESPACE :
+    case COLORINDEX_BKGND:
+      return::GetSysColor (COLOR_WINDOW);
+    case COLORINDEX_NORMALTEXT:
+      return::GetSysColor (COLOR_WINDOWTEXT);
+    case COLORINDEX_SELMARGIN:
+      return::GetSysColor (COLOR_SCROLLBAR);
+    case COLORINDEX_PREPROCESSOR:
+      return RGB (0, 128, 192);
+    case COLORINDEX_COMMENT:
+      //      return RGB(128, 128, 128);
+      return RGB (0, 128, 0);
+      //  [JRT]: Enabled Support For Numbers...
+    case COLORINDEX_NUMBER:
+      //      return RGB(0x80, 0x00, 0x00);
+      return RGB (0xff, 0x00, 0x00);
+      //  [JRT]: Support For C/C++ Operators
+    case COLORINDEX_OPERATOR:
+      //      return RGB(0x00, 0x00, 0x00);
+      return RGB (96, 96, 96);
+    case COLORINDEX_KEYWORD:
+      return RGB (0, 0, 255);
+    case COLORINDEX_FUNCNAME:
+      return RGB (128, 0, 128);
+    case COLORINDEX_USER1:
+      return RGB (0, 0, 128);
+    case COLORINDEX_USER2:
+      return RGB (0, 128, 192);
+    case COLORINDEX_SELBKGND:
+      return RGB (0, 0, 0);
+    case COLORINDEX_SELTEXT:
+      return RGB (255, 255, 255);
+    }
+  //  return RGB(255, 0, 0);
+  return RGB (128, 0, 0);
+}
+
+DWORD CCrystalTextView::
+GetLineFlags (int nLineIndex)
+{
+  if (m_pTextBuffer == NULL)
+    return 0;
+  return m_pTextBuffer->GetLineFlags (nLineIndex);
+}
+
+void CCrystalTextView::
+DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex)
+{
+  if (!m_bSelMargin)
+    {
+      pdc->FillSolidRect (rect, GetColor (COLORINDEX_BKGND));
+      return;
+    }
+
+  pdc->FillSolidRect (rect, GetColor (COLORINDEX_SELMARGIN));
+
+  int nImageIndex = -1;
+  if (nLineIndex >= 0)
+    {
+      DWORD dwLineFlags = GetLineFlags (nLineIndex);
+      static const DWORD adwFlags[] =
+        {
+          LF_EXECUTION,
+          LF_BREAKPOINT,
+          LF_COMPILATION_ERROR,
+          LF_BOOKMARK (1),
+          LF_BOOKMARK (2),
+          LF_BOOKMARK (3),
+          LF_BOOKMARK (4),
+          LF_BOOKMARK (5),
+          LF_BOOKMARK (6),
+          LF_BOOKMARK (7),
+          LF_BOOKMARK (8),
+          LF_BOOKMARK (9),
+          LF_BOOKMARK (0),
+          LF_BOOKMARKS,
+          LF_INVALID_BREAKPOINT
+        };
+      for (int I = 0; I <= sizeof (adwFlags) / sizeof (adwFlags[0]); I++)
+        {
+          if ((dwLineFlags & adwFlags[I]) != 0)
+            {
+              nImageIndex = I;
+              break;
+            }
+        }
+    }
+
+  if (nImageIndex >= 0)
+    {
+      if (m_pIcons == NULL)
+        {
+          m_pIcons = new CImageList;
+          VERIFY (m_pIcons->Create (IDR_MARGIN_ICONS, 16, 16, RGB (255, 255, 255)));
+        }
+               //BEGIN SW
+               CPoint pt(rect.left + 2, rect.top + (GetLineHeight() - 16) / 2);
+               /*ORIGINAL
+               CPoint pt(rect.left + 2, rect.top + (rect.Height() - 16) / 2);
+               *///END SW
+               VERIFY(m_pIcons->Draw(pdc, nImageIndex, pt, ILD_TRANSPARENT));
+      VERIFY (m_pIcons->Draw (pdc, nImageIndex, pt, ILD_TRANSPARENT));
+    }
+}
+
+BOOL CCrystalTextView::
+IsInsideSelBlock (CPoint ptTextPos)
+{
+  ASSERT_VALIDTEXTPOS (ptTextPos);
+  if (ptTextPos.y < m_ptDrawSelStart.y)
+    return FALSE;
+  if (ptTextPos.y > m_ptDrawSelEnd.y)
+    return FALSE;
+  if (ptTextPos.y < m_ptDrawSelEnd.y && ptTextPos.y > m_ptDrawSelStart.y)
+    return TRUE;
+  if (m_ptDrawSelStart.y < m_ptDrawSelEnd.y)
+    {
+      if (ptTextPos.y == m_ptDrawSelEnd.y)
+        return ptTextPos.x < m_ptDrawSelEnd.x;
+      ASSERT (ptTextPos.y == m_ptDrawSelStart.y);
+      return ptTextPos.x >= m_ptDrawSelStart.x;
+    }
+  ASSERT (m_ptDrawSelStart.y == m_ptDrawSelEnd.y);
+  return ptTextPos.x >= m_ptDrawSelStart.x && ptTextPos.x < m_ptDrawSelEnd.x;
+}
+
+BOOL CCrystalTextView::
+IsInsideSelection (const CPoint & ptTextPos)
+{
+  PrepareSelBounds ();
+  return IsInsideSelBlock (ptTextPos);
+}
+
+void CCrystalTextView::
+PrepareSelBounds ()
+{
+  if (m_ptSelStart.y < m_ptSelEnd.y ||
+        (m_ptSelStart.y == m_ptSelEnd.y && m_ptSelStart.x < m_ptSelEnd.x))
+    {
+      m_ptDrawSelStart = m_ptSelStart;
+      m_ptDrawSelEnd = m_ptSelEnd;
+    }
+  else
+    {
+      m_ptDrawSelStart = m_ptSelEnd;
+      m_ptDrawSelEnd = m_ptSelStart;
+    }
+}
+
+void CCrystalTextView::
+OnDraw (CDC * pdc)
+{
+  CRect rcClient;
+  GetClientRect (rcClient);
+
+  int nLineCount = GetLineCount ();
+  int nLineHeight = GetLineHeight ();
+  PrepareSelBounds ();
+
+  CDC cacheDC;
+  VERIFY (cacheDC.CreateCompatibleDC (pdc));
+  if (m_pCacheBitmap == NULL)
+    {
+      m_pCacheBitmap = new CBitmap;
+               //BEGIN SW
+               VERIFY(m_pCacheBitmap->CreateCompatibleBitmap(pdc, rcClient.Width(), rcClient.Height()));
+               /*ORIGINAL
+               VERIFY(m_pCacheBitmap->CreateCompatibleBitmap(pdc, rcClient.Width(), nLineHeight));
+               */
+               //END SW
+    }
+  CBitmap *pOldBitmap = cacheDC.SelectObject (m_pCacheBitmap);
+
+  CRect rcLine;
+  rcLine = rcClient;
+  rcLine.bottom = rcLine.top + nLineHeight;
+  CRect rcCacheMargin (0, 0, GetMarginWidth (), nLineHeight);
+  CRect rcCacheLine (GetMarginWidth (), 0, rcLine.Width (), nLineHeight);
+       //BEGIN SW
+       // initialize rects
+       int             nSubLineOffset = GetSubLineIndex( m_nTopLine ) - m_nTopSubLine;
+       if( nSubLineOffset < 0 )
+       {
+               rcCacheMargin.OffsetRect( 0, nSubLineOffset * nLineHeight );
+               rcCacheLine.OffsetRect( 0, nSubLineOffset * nLineHeight );
+       }
+
+       int             nBreaks;
+       int             nMaxLineChars = GetScreenChars();
+       //END SW
+
+  int nCurrentLine = m_nTopLine;
+  while (rcLine.top < rcClient.bottom)
+    {
+               //BEGIN SW
+               nBreaks = 0;
+               if( nCurrentLine < nLineCount /*&& GetLineLength( nCurrentLine ) > nMaxLineChars*/ )
+                       WrapLineCached( nCurrentLine, nMaxLineChars, NULL, nBreaks );
+
+               rcLine.bottom = rcLine.top + (nBreaks + 1) * nLineHeight;
+               rcCacheLine.bottom = rcCacheLine.top + rcLine.Height();
+               rcCacheMargin.bottom = rcCacheMargin.top + rcLine.Height();
+
+               if( rcCacheLine.top < 0 )
+                       rcLine.bottom+= rcCacheLine.top;
+               //END SW
+      if (nCurrentLine < nLineCount)
+        {
+          DrawMargin (&cacheDC, rcCacheMargin, nCurrentLine);
+          DrawSingleLine (&cacheDC, rcCacheLine, nCurrentLine);
+        }
+      else
+        {
+          DrawMargin (&cacheDC, rcCacheMargin, -1);
+          DrawSingleLine (&cacheDC, rcCacheLine, -1);
+        }
+
+      VERIFY (pdc->BitBlt (rcLine.left, rcLine.top, rcLine.Width (), rcLine.Height (), &cacheDC, 0, 0, SRCCOPY));
+
+      nCurrentLine++;
+               //BEGIN SW
+               rcLine.top = rcLine.bottom;
+               rcCacheLine.top = 0;
+               rcCacheMargin.top = 0;
+               /*ORIGINAL
+               rcLine.OffsetRect(0, nLineHeight);
+               */
+               //END SW
+    }
+
+  cacheDC.SelectObject (pOldBitmap);
+  cacheDC.DeleteDC ();
+}
+
+void CCrystalTextView::
+ResetView ()
+{
+  // m_bWordWrap = FALSE;
+  m_nTopLine = 0;
+  m_nOffsetChar = 0;
+  m_nLineHeight = -1;
+  m_nCharWidth = -1;
+  m_nTabSize = 4;
+  m_nMaxLineLength = -1;
+  m_nScreenLines = -1;
+  m_nScreenChars = -1;
+  m_nIdealCharPos = -1;
+  m_ptAnchor.x = 0;
+  m_ptAnchor.y = 0;
+  if (m_pIcons != NULL)
+    {
+      delete m_pIcons;
+      m_pIcons = NULL;
+    }
+  for (int I = 0; I < 4; I++)
+    {
+      if (m_apFonts[I] != NULL)
+        {
+          m_apFonts[I]->DeleteObject ();
+          delete m_apFonts[I];
+          m_apFonts[I] = NULL;
+        }
+    }
+  if (m_pdwParseCookies != NULL)
+    {
+      delete m_pdwParseCookies;
+      m_pdwParseCookies = NULL;
+    }
+  if (m_pnActualLineLength != NULL)
+    {
+      delete m_pnActualLineLength;
+      m_pnActualLineLength = NULL;
+    }
+  m_nParseArraySize = 0;
+  m_nActualLengthArraySize = 0;
+  m_ptCursorPos.x = 0;
+  m_ptCursorPos.y = 0;
+  m_ptSelStart = m_ptSelEnd = m_ptCursorPos;
+  m_bDragSelection = FALSE;
+  m_bVertScrollBarLocked = FALSE;
+  m_bHorzScrollBarLocked = FALSE;
+  if (::IsWindow (m_hWnd))
+    UpdateCaret ();
+  m_bLastSearch = FALSE;
+  m_bShowInactiveSelection = TRUE; // FP: reverted because I like it
+  m_bPrintHeader = FALSE;
+  m_bPrintFooter = TRUE;
+
+  m_bBookmarkExist = FALSE;     // More bookmarks
+
+  m_bMultipleSearch = FALSE;    // More search
+
+}
+
+void CCrystalTextView::
+UpdateCaret ()
+{
+  ASSERT_VALIDTEXTPOS (m_ptCursorPos);
+  if (m_bFocused && !m_bCursorHidden &&
+        CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x) >= m_nOffsetChar)
+    {
+      CreateSolidCaret (2, GetLineHeight ());
+      SetCaretPos (TextToClient (m_ptCursorPos));
+      ShowCaret ();
+    }
+  else
+    {
+      HideCaret ();
+    }
+}
+
+int CCrystalTextView::
+GetCRLFMode ()
+{
+  if (m_pTextBuffer)
+    {
+      return m_pTextBuffer->GetCRLFMode ();
+    }
+  return -1;
+}
+
+void CCrystalTextView::
+SetCRLFMode (int nCRLFMode)
+{
+  if (m_pTextBuffer)
+    {
+      m_pTextBuffer->SetCRLFMode (nCRLFMode);
+    }
+}
+
+int CCrystalTextView::
+GetTabSize ()
+{
+  ASSERT (m_nTabSize >= 0 && m_nTabSize <= 64);
+  return m_nTabSize;
+}
+
+void CCrystalTextView::
+SetTabSize (int nTabSize)
+{
+  ASSERT (nTabSize >= 0 && nTabSize <= 64);
+  if (m_nTabSize != nTabSize)
+    {
+      m_nTabSize = nTabSize;
+      if (m_pnActualLineLength != NULL)
+        {
+          delete m_pnActualLineLength;
+          m_pnActualLineLength = NULL;
+        }
+      m_nActualLengthArraySize = 0;
+      m_nMaxLineLength = -1;
+      RecalcHorzScrollBar ();
+      Invalidate ();
+      UpdateCaret ();
+    }
+}
+
+CFont *CCrystalTextView::
+GetFont (BOOL bItalic /*= FALSE*/ , BOOL bBold /*= FALSE*/ )
+{
+  int nIndex = 0;
+  if (bBold)
+    nIndex |= 1;
+  if (bItalic)
+    nIndex |= 2;
+
+  if (m_apFonts[nIndex] == NULL)
+    {
+      m_apFonts[nIndex] = new CFont;
+      if (!m_lfBaseFont.lfHeight)
+        {
+          CClientDC dc (GetDesktopWindow ());
+          m_lfBaseFont.lfHeight = -MulDiv (11, dc.GetDeviceCaps (LOGPIXELSY), 72);
+        }
+      m_lfBaseFont.lfWeight = bBold && !_tcsnicmp (m_lfBaseFont.lfFaceName, _T ("Courier"), 7) ? FW_BOLD : FW_NORMAL;
+      m_lfBaseFont.lfItalic = (BYTE) (bItalic && !_tcsnicmp (m_lfBaseFont.lfFaceName, _T ("Courier"), 7));
+      if (!m_apFonts[nIndex]->CreateFontIndirect (&m_lfBaseFont))
+        {
+          delete m_apFonts[nIndex];
+          m_apFonts[nIndex] = NULL;
+          return CView::GetFont ();
+        }
+
+    }
+  return m_apFonts[nIndex];
+}
+
+void CCrystalTextView::
+CalcLineCharDim ()
+{
+  CDC *pdc = GetDC ();
+  CFont *pOldFont = pdc->SelectObject (GetFont ());
+  CSize szCharExt = pdc->GetTextExtent (_T ("X"));
+  m_nLineHeight = szCharExt.cy;
+  if (m_nLineHeight < 1)
+    m_nLineHeight = 1;
+  m_nCharWidth = szCharExt.cx;
+  /*
+     TEXTMETRIC tm;
+     if (pdc->GetTextMetrics(&tm))
+     m_nCharWidth -= tm.tmOverhang;
+   */
+  pdc->SelectObject (pOldFont);
+  ReleaseDC (pdc);
+}
+
+int CCrystalTextView::
+GetLineHeight ()
+{
+  if (m_nLineHeight == -1)
+    CalcLineCharDim ();
+  return m_nLineHeight;
+}
+
+//BEGIN SW
+int CCrystalTextView::GetSubLines( int nLineIndex )
+{
+       /*
+       if( GetLineLength( nLineIndex ) <= GetScreenChars() )
+               return 1;
+       */
+       // get number of wrapped lines, this line contains of
+       int     nBreaks = 0;
+       WrapLineCached( nLineIndex, GetScreenChars(), NULL, nBreaks );
+
+       return nBreaks + 1;
+}
+
+int CCrystalTextView::CharPosToPoint( int nLineIndex, int nCharPos, CPoint &charPoint )
+{
+       // if we do not wrap lines, y is allways 0 and x is equl to nCharPos
+       if( !m_bWordWrap )
+       {
+               charPoint.x = nCharPos;
+               charPoint.y = 0;
+       }
+
+       // calculate point out of char pos
+       /*
+       if( GetLineLength( nLineIndex ) <= GetScreenChars() )
+       {
+               // line is not wrapped
+               charPoint.x = nCharPos;
+               charPoint.y = 0;
+               return 0;
+       }
+       */
+
+       // line is wrapped
+       int *anBreaks = (int*)_alloca( sizeof( int ) * GetLineLength( nLineIndex ) );
+       int     nBreaks = 0;
+
+       WrapLineCached( nLineIndex, GetScreenChars(), anBreaks, nBreaks );
+
+       for( int i = nBreaks - 1; i >= 0 && nCharPos < anBreaks[i]; i-- );
+
+       charPoint.x = (i >= 0)? nCharPos - anBreaks[i] : nCharPos;
+       charPoint.y = i + 1;
+
+       return (i >= 0)? anBreaks[i] : 0;
+}
+
+int CCrystalTextView::CursorPointToCharPos( int nLineIndex, const CPoint &curPoint )
+{
+       // calculate char pos out of point
+       int                     nLength = GetLineLength( nLineIndex );
+       int                     nScreenChars = GetScreenChars();
+       LPCTSTR szLine = GetLineChars( nLineIndex );
+
+       // wrap line
+       int *anBreaks = (int*)_alloca( sizeof( int ) * nLength );
+       int     nBreaks = 0;
+
+       WrapLineCached( nLineIndex, nScreenChars, anBreaks, nBreaks );
+
+       // find char pos that matches cursor position
+       int nXPos = 0;
+       int nYPos = 0;
+       int     nCurPos = 0;
+       int nTabSize = GetTabSize();
+
+       for( int nIndex = 0; nIndex < nLength; nIndex++ )
+       {
+               if( nBreaks && nIndex == anBreaks[nYPos] )
+               {
+                       nXPos = 0;
+                       nYPos++;
+               }
+
+               if (szLine[nIndex] == _T('\t'))
+               {
+                       nXPos+= (nTabSize - nCurPos % nTabSize);
+                       nCurPos+= (nTabSize - nCurPos % nTabSize);
+               }
+               else
+               {
+                       nXPos++;
+                       nCurPos++;
+               }
+
+               if( nXPos > curPoint.x && nYPos == curPoint.y )
+                       break;
+               else if( nYPos > curPoint.y )
+               {
+                       nIndex--;
+                       break;
+               }
+       }
+
+       return nIndex;  
+}
+
+void CCrystalTextView::SubLineCursorPosToTextPos( const CPoint &subLineCurPos, CPoint &textPos )
+{
+       // Get line breaks
+       int     nSubLineOffset, nLine;
+
+       GetLineBySubLine( subLineCurPos.y, nLine, nSubLineOffset );
+
+       // compute cursor-position
+       textPos.x = CursorPointToCharPos( nLine, CPoint( subLineCurPos.x, nSubLineOffset ) );
+       textPos.y = nLine;
+}
+
+int CCrystalTextView::SubLineEndToCharPos( int nLineIndex, int nSubLineOffset )
+{
+       int             nLength = GetLineLength( nLineIndex );
+
+       // if word wrapping is disabled, the end is equal to the length of the line -1
+       if( !m_bWordWrap /*|| nLength <= GetScreenChars()*/ )
+               return nLength;
+
+       // wrap line
+       int *anBreaks = (int*)_alloca( sizeof( int ) * nLength );
+       int     nBreaks = 0;
+
+       WrapLineCached( nLineIndex, GetScreenChars(), anBreaks, nBreaks );
+
+       // if there is no break inside the line or the given subline is the last
+       // one in this line...
+       if( !nBreaks || nSubLineOffset == nBreaks )
+               return nLength;
+
+       // compute character position for end of subline
+       ASSERT( nSubLineOffset >= 0 && nSubLineOffset <= nBreaks );
+       
+       return anBreaks[nSubLineOffset] - 1;
+}
+
+int CCrystalTextView::SubLineHomeToCharPos( int nLineIndex, int nSubLineOffset )
+{
+       int             nLength = GetLineLength( nLineIndex );
+
+       // if word wrapping is disabled, the start is 0
+       if( !m_bWordWrap /*|| nLength <= GetScreenChars() */|| nSubLineOffset == 0 )
+               return 0;
+
+       // wrap line
+       int *anBreaks = (int*)_alloca( sizeof( int ) * nLength );
+       int     nBreaks = 0;
+
+       WrapLineCached( nLineIndex, GetScreenChars(), anBreaks, nBreaks );
+
+       // if there is no break inside the line...
+       if( !nBreaks )
+               return 0;
+
+       // compute character position for end of subline
+       ASSERT( nSubLineOffset > 0 && nSubLineOffset <= nBreaks );
+       
+       return anBreaks[nSubLineOffset - 1];
+}
+//END SW
+
+int CCrystalTextView::
+GetCharWidth ()
+{
+  if (m_nCharWidth == -1)
+    CalcLineCharDim ();
+  return m_nCharWidth;
+}
+
+int CCrystalTextView::
+GetMaxLineLength ()
+{
+  if (m_nMaxLineLength == -1)
+    {
+      m_nMaxLineLength = 0;
+      int nLineCount = GetLineCount ();
+      for (int I = 0; I < nLineCount; I++)
+        {
+          int nActualLength = GetLineActualLength (I);
+          if (m_nMaxLineLength < nActualLength)
+            m_nMaxLineLength = nActualLength;
+        }
+    }
+  return m_nMaxLineLength;
+}
+
+CCrystalTextView *CCrystalTextView::
+GetSiblingView (int nRow, int nCol)
+{
+  CSplitterWnd *pSplitter = GetParentSplitter (this, FALSE);
+  if (pSplitter == NULL)
+    return NULL;
+  CWnd *pWnd = CWnd::FromHandlePermanent (
+                 ::GetDlgItem (pSplitter->m_hWnd, pSplitter->IdFromRowCol (nRow, nCol)));
+  if (pWnd == NULL || !pWnd->IsKindOf (RUNTIME_CLASS (CCrystalTextView)))
+    return NULL;
+  return (CCrystalTextView *) pWnd;
+}
+
+void CCrystalTextView::
+GoToLine (int nLine, bool bRelative)
+{
+  int nLines = m_pTextBuffer->GetLineCount () - 1;
+  CPoint ptCursorPos = GetCursorPos ();
+  if (bRelative)
+    {
+      nLine += ptCursorPos.y;
+    }
+  if (nLine)
+    {
+      nLine--;
+    }
+  if (nLine > nLines)
+    {
+      nLine = nLines;
+    }
+  if (nLine >= 0)
+    {
+      int nChars = m_pTextBuffer->GetLineLength (nLine);
+      if (nChars)
+        {
+          nChars--;
+        }
+      if (ptCursorPos.x > nChars)
+        {
+          ptCursorPos.x = nChars;
+        }
+      if (ptCursorPos.x >= 0)
+        {
+          ptCursorPos.y = nLine;
+          ASSERT_VALIDTEXTPOS (ptCursorPos);
+          SetAnchor (ptCursorPos);
+          SetSelection (ptCursorPos, ptCursorPos);
+          SetCursorPos (ptCursorPos);
+          EnsureVisible (ptCursorPos);
+        }
+    }
+}
+
+void CCrystalTextView::
+OnInitialUpdate ()
+{
+  CView::OnInitialUpdate ();
+  CString sDoc = GetDocument ()->GetPathName (), sExt = GetExt (sDoc);
+  SetTextType (sExt);
+  AttachToBuffer (NULL);
+
+  CSplitterWnd *pSplitter = GetParentSplitter (this, FALSE);
+  if (pSplitter != NULL)
+    {
+      //  See CSplitterWnd::IdFromRowCol() implementation
+      int nRow = (GetDlgCtrlID () - AFX_IDW_PANE_FIRST) / 16;
+      int nCol = (GetDlgCtrlID () - AFX_IDW_PANE_FIRST) % 16;
+      ASSERT (nRow >= 0 && nRow < pSplitter->GetRowCount ());
+      ASSERT (nCol >= 0 && nCol < pSplitter->GetColumnCount ());
+
+      if (nRow > 0)
+        {
+          CCrystalTextView *pSiblingView = GetSiblingView (0, nCol);
+          if (pSiblingView != NULL && pSiblingView != this)
+            {
+              m_nOffsetChar = pSiblingView->m_nOffsetChar;
+              ASSERT (m_nOffsetChar >= 0 && m_nOffsetChar <= GetMaxLineLength ());
+            }
+        }
+
+      if (nCol > 0)
+        {
+          CCrystalTextView *pSiblingView = GetSiblingView (nRow, 0);
+          if (pSiblingView != NULL && pSiblingView != this)
+            {
+              m_nTopLine = pSiblingView->m_nTopLine;
+              ASSERT (m_nTopLine >= 0 && m_nTopLine < GetLineCount ());
+            }
+        }
+    }
+  SetTextType (sExt);
+  SetFont (m_LogFont);
+  if (m_bRememberLastPos && !sDoc.IsEmpty ())
+    {
+      DWORD dwLastPos[3];
+      CString sKey = REG_EDITPAD;
+      sKey += _T ("\\Remembered");
+      CReg reg;
+      if (reg.Open (HKEY_CURRENT_USER, sKey, KEY_READ) &&
+        reg.LoadBinary (sDoc, (LPBYTE) dwLastPos, sizeof (dwLastPos)))
+        {
+          CPoint ptCursorPos;
+          ptCursorPos.x = dwLastPos[1];
+          ptCursorPos.y = dwLastPos[2];
+          if (IsValidTextPosY (ptCursorPos))
+            {
+              if (!IsValidTextPosX (ptCursorPos))
+                ptCursorPos.x = 0;
+              ASSERT_VALIDTEXTPOS (ptCursorPos);
+              SetCursorPos (ptCursorPos);
+              SetSelection (ptCursorPos, ptCursorPos);
+              SetAnchor (ptCursorPos);
+              EnsureVisible (ptCursorPos);
+            }
+        }
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextView printing
+
+void CCrystalTextView::
+OnPrepareDC (CDC * pDC, CPrintInfo * pInfo)
+{
+  CView::OnPrepareDC (pDC, pInfo);
+
+  if (pInfo != NULL)
+    {
+      pInfo->m_bContinuePrinting = TRUE;
+      if (m_pnPages != NULL && (int) pInfo->m_nCurPage > m_nPrintPages)
+        pInfo->m_bContinuePrinting = FALSE;
+    }
+}
+
+BOOL CCrystalTextView::
+OnPreparePrinting (CPrintInfo * pInfo)
+{
+  return DoPreparePrinting (pInfo);
+}
+
+int CCrystalTextView::
+PrintLineHeight (CDC * pdc, int nLine)
+{
+  ASSERT (nLine >= 0 && nLine < GetLineCount ());
+  ASSERT (m_nPrintLineHeight > 0);
+  int nLength = GetLineLength (nLine);
+  if (nLength == 0)
+    return m_nPrintLineHeight;
+
+  CString line;
+  LPCTSTR pszChars = GetLineChars (nLine);
+  ExpandChars (pszChars, 0, nLength, line);
+  CRect rcPrintArea = m_rcPrintArea;
+  pdc->DrawText (line, &rcPrintArea, DT_LEFT | DT_NOPREFIX | DT_TOP | DT_WORDBREAK | DT_CALCRECT);
+  return rcPrintArea.Height ();
+}
+
+void CCrystalTextView::
+GetPrintHeaderText (int nPageNum, CString & text)
+{
+  ASSERT (m_bPrintHeader);
+  text = _T ("");
+}
+
+void CCrystalTextView::
+GetPrintFooterText (int nPageNum, CString & text)
+{
+  ASSERT (m_bPrintFooter);
+  text.Format (_T ("Page %d/%d"), nPageNum, m_nPrintPages);
+}
+
+void CCrystalTextView::
+PrintHeader (CDC * pdc, int nPageNum)
+{
+  CRect rcHeader = m_rcPrintArea;
+  rcHeader.bottom = rcHeader.top;
+  rcHeader.top -= (m_nPrintLineHeight + m_nPrintLineHeight / 2);
+
+  CString text;
+  GetPrintHeaderText (nPageNum, text);
+  if (!text.IsEmpty ())
+    pdc->DrawText (text, &rcHeader, DT_CENTER | DT_NOPREFIX | DT_TOP | DT_SINGLELINE);
+}
+
+void CCrystalTextView::
+PrintFooter (CDC * pdc, int nPageNum)
+{
+  CRect rcFooter = m_rcPrintArea;
+  rcFooter.top = rcFooter.bottom;
+  rcFooter.bottom += (m_nPrintLineHeight + m_nPrintLineHeight / 2);
+
+  CString text;
+  GetPrintFooterText (nPageNum, text);
+  if (!text.IsEmpty ())
+    pdc->DrawText (text, &rcFooter, DT_CENTER | DT_NOPREFIX | DT_BOTTOM | DT_SINGLELINE);
+}
+
+void CCrystalTextView::
+RecalcPageLayouts (CDC * pdc, CPrintInfo * pInfo)
+{
+  m_ptPageArea = pInfo->m_rectDraw;
+  m_ptPageArea.NormalizeRect ();
+
+  m_nPrintLineHeight = pdc->GetTextExtent (_T ("X")).cy;
+
+  m_rcPrintArea = m_ptPageArea;
+  CSize szTopLeft, szBottomRight;
+  CWinApp *pApp = AfxGetApp ();
+  ASSERT (pApp != NULL);
+  szTopLeft.cx = DEFAULT_PRINT_MARGIN;
+  szBottomRight.cx = DEFAULT_PRINT_MARGIN;
+  szTopLeft.cy = DEFAULT_PRINT_MARGIN;
+  szBottomRight.cy = DEFAULT_PRINT_MARGIN;
+  CReg reg;
+  if (reg.Open (HKEY_CURRENT_USER, REG_EDITPAD, KEY_READ))
+    {
+      DWORD dwTemp;
+      if (reg.LoadNumber (_T ("PageLeft"), &dwTemp))
+        szTopLeft.cx = dwTemp;
+      if (reg.LoadNumber (_T ("PageRight"), &dwTemp))
+        szBottomRight.cx = dwTemp;
+      if (reg.LoadNumber (_T ("PageTop"), &dwTemp))
+        szTopLeft.cy = dwTemp;
+      if (reg.LoadNumber (_T ("PageBottom"), &dwTemp))
+        szBottomRight.cy = dwTemp;
+    }
+  pdc->HIMETRICtoLP (&szTopLeft);
+  pdc->HIMETRICtoLP (&szBottomRight);
+  m_rcPrintArea.left += szTopLeft.cx;
+  m_rcPrintArea.right -= szBottomRight.cx;
+  m_rcPrintArea.top += szTopLeft.cy;
+  m_rcPrintArea.bottom -= szBottomRight.cy;
+  if (m_bPrintHeader)
+    m_rcPrintArea.top += m_nPrintLineHeight + m_nPrintLineHeight / 2;
+  if (m_bPrintFooter)
+    m_rcPrintArea.bottom += m_nPrintLineHeight + m_nPrintLineHeight / 2;
+
+  int nLimit = 32;
+  m_nPrintPages = 1;
+  m_pnPages = new int[nLimit];
+  m_pnPages[0] = 0;
+
+  int nLineCount = GetLineCount ();
+  int nLine = 1;
+  int y = m_rcPrintArea.top + PrintLineHeight (pdc, 0);
+  while (nLine < nLineCount)
+    {
+      int nHeight = PrintLineHeight (pdc, nLine);
+      if (y + nHeight <= m_rcPrintArea.bottom)
+        {
+          y += nHeight;
+        }
+      else
+        {
+          ASSERT (nLimit >= m_nPrintPages);
+          if (nLimit <= m_nPrintPages)
+            {
+              nLimit += 32;
+              int *pnNewPages = new int[nLimit];
+              memcpy (pnNewPages, m_pnPages, sizeof (int) * m_nPrintPages);
+              delete m_pnPages;
+              m_pnPages = pnNewPages;
+            }
+          ASSERT (nLimit > m_nPrintPages);
+          m_pnPages[m_nPrintPages++] = nLine;
+          y = m_rcPrintArea.top + nHeight;
+        }
+      nLine++;
+    }
+}
+
+void CCrystalTextView::
+OnBeginPrinting (CDC * pdc, CPrintInfo * pInfo)
+{
+  ASSERT (m_pnPages == NULL);
+  ASSERT (m_pPrintFont == NULL);
+  CFont *pDisplayFont = GetFont ();
+
+  LOGFONT lf;
+  pDisplayFont->GetLogFont (&lf);
+
+  CDC *pDisplayDC = GetDC ();
+  lf.lfHeight = MulDiv (lf.lfHeight, pdc->GetDeviceCaps (LOGPIXELSY), pDisplayDC->GetDeviceCaps (LOGPIXELSY) * 2);
+  lf.lfWidth = MulDiv (lf.lfWidth, pdc->GetDeviceCaps (LOGPIXELSX), pDisplayDC->GetDeviceCaps (LOGPIXELSX) * 2);
+  ReleaseDC (pDisplayDC);
+
+  m_pPrintFont = new CFont;
+  if (!m_pPrintFont->CreateFontIndirect (&lf))
+    {
+      delete m_pPrintFont;
+      m_pPrintFont = NULL;
+      return;
+    }
+
+  pdc->SelectObject (m_pPrintFont);
+}
+
+void CCrystalTextView::
+OnEndPrinting (CDC * pdc, CPrintInfo * pInfo)
+{
+  if (m_pPrintFont != NULL)
+    {
+      delete m_pPrintFont;
+      m_pPrintFont = NULL;
+    }
+  if (m_pnPages != NULL)
+    {
+      delete m_pnPages;
+      m_pnPages = NULL;
+    }
+  m_nPrintPages = 0;
+  m_nPrintLineHeight = 0;
+}
+
+void CCrystalTextView::
+OnPrint (CDC * pdc, CPrintInfo * pInfo)
+{
+  if (m_pnPages == NULL)
+    {
+      RecalcPageLayouts (pdc, pInfo);
+      ASSERT (m_pnPages != NULL);
+    }
+
+  ASSERT (pInfo->m_nCurPage >= 1 && (int) pInfo->m_nCurPage <= m_nPrintPages);
+  int nLine = m_pnPages[pInfo->m_nCurPage - 1];
+  int nEndLine = GetLineCount ();
+  if ((int) pInfo->m_nCurPage < m_nPrintPages)
+    nEndLine = m_pnPages[pInfo->m_nCurPage];
+  TRACE (_T ("Printing page %d of %d, lines %d - %d\n"), pInfo->m_nCurPage, m_nPrintPages,
+         nLine, nEndLine - 1);
+
+  if (m_bPrintHeader)
+    PrintHeader (pdc, pInfo->m_nCurPage);
+  if (m_bPrintFooter)
+    PrintFooter (pdc, pInfo->m_nCurPage);
+
+  int y = m_rcPrintArea.top;
+  for (; nLine < nEndLine; nLine++)
+    {
+      int nLineLength = GetLineLength (nLine);
+      if (nLineLength == 0)
+        {
+          y += m_nPrintLineHeight;
+          continue;
+        }
+
+      CRect rcPrintRect = m_rcPrintArea;
+      rcPrintRect.top = y;
+      LPCTSTR pszChars = GetLineChars (nLine);
+      CString line;
+      ExpandChars (pszChars, 0, nLineLength, line);
+      y += pdc->DrawText (line, &rcPrintRect, DT_LEFT | DT_NOPREFIX | DT_TOP | DT_WORDBREAK);
+    }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextView message handlers
+
+int CCrystalTextView::
+GetLineCount ()
+{
+  if (m_pTextBuffer == NULL)
+    return 1;                   //  Single empty line
+
+  int nLineCount = m_pTextBuffer->GetLineCount ();
+  ASSERT (nLineCount > 0);
+  return nLineCount;
+}
+
+//BEGIN SW
+int CCrystalTextView::GetSubLineCount()
+{
+       // if we do not wrap words, number of sub lines is equal to number of lines
+       if( !m_bWordWrap )
+               return GetLineCount();
+
+       // calculate number of sub lines
+       int     nLineCount = GetLineCount();
+       int nSubLineCount = 0;
+
+       for( int i = 0; i < nLineCount; i++ )
+               nSubLineCount+= GetSubLines( i );
+
+       return nSubLineCount;
+}
+
+int CCrystalTextView::GetSubLineIndex( int nLineIndex )
+{
+       // if we do not wrap words, subline index of this line is equal to its index
+       if( !m_bWordWrap )
+               return nLineIndex;
+
+       // calculate subline index of the line
+       int     nSubLineCount = 0;
+
+       if( nLineIndex >= GetLineCount() )
+               nLineIndex = GetLineCount() - 1;
+
+       for( int i = 0; i < nLineIndex; i++ )
+               nSubLineCount+= GetSubLines( i );
+
+       return nSubLineCount;
+}
+
+void CCrystalTextView::GetLineBySubLine( int nSubLineIndex, int &nLine, int &nSubLine )
+{
+       ASSERT( nSubLineIndex < GetSubLineCount() );
+
+       // if we do not wrap words, nLine is equal to nSubLineIndex and nSubLine is allways 0
+       if( !m_bWordWrap )
+       {
+               nLine = nSubLineIndex;
+               nSubLine = 0;
+       }
+
+       // compute result
+       int     nSubLineCount = 0;
+       int     nLineCount = GetLineCount();
+
+       for( int i = 0; i < nLineCount; i++ )
+       {
+               nSubLineCount+= GetSubLines( i );
+               if( !(nSubLineCount <= nSubLineIndex) )
+                       break;
+       }
+
+       ASSERT( i < nLineCount );
+       nLine = i;
+       nSubLine = nSubLineIndex - (nSubLineCount - GetSubLines( i ));
+}
+//END SW
+
+int CCrystalTextView::
+GetLineLength (int nLineIndex)
+{
+  if (m_pTextBuffer == NULL)
+    return 0;
+  return m_pTextBuffer->GetLineLength (nLineIndex);
+}
+
+LPCTSTR CCrystalTextView::
+GetLineChars (int nLineIndex)
+{
+  if (m_pTextBuffer == NULL)
+    return NULL;
+  return m_pTextBuffer->GetLineChars (nLineIndex);
+}
+
+void CCrystalTextView::
+AttachToBuffer (CCrystalTextBuffer * pBuf /*= NULL*/ )
+{
+  if (m_pTextBuffer != NULL)
+    m_pTextBuffer->RemoveView (this);
+  if (pBuf == NULL)
+    {
+      pBuf = LocateTextBuffer ();
+      //  ...
+    }
+  m_pTextBuffer = pBuf;
+  if (m_pTextBuffer != NULL)
+    m_pTextBuffer->AddView (this);
+  ResetView ();
+
+  //  Init scrollbars
+  CScrollBar *pVertScrollBarCtrl = GetScrollBarCtrl (SB_VERT);
+  if (pVertScrollBarCtrl != NULL)
+    pVertScrollBarCtrl->EnableScrollBar (GetScreenLines () >= GetLineCount ()?
+                                         ESB_DISABLE_BOTH : ESB_ENABLE_BOTH);
+  CScrollBar *pHorzScrollBarCtrl = GetScrollBarCtrl (SB_HORZ);
+  if (pHorzScrollBarCtrl != NULL)
+    pHorzScrollBarCtrl->EnableScrollBar (GetScreenChars () >= GetMaxLineLength ()?
+                                         ESB_DISABLE_BOTH : ESB_ENABLE_BOTH);
+
+  //  Update scrollbars
+  RecalcVertScrollBar ();
+  RecalcHorzScrollBar ();
+}
+
+void CCrystalTextView::
+DetachFromBuffer ()
+{
+  if (m_pTextBuffer != NULL)
+    {
+      m_pTextBuffer->RemoveView (this);
+      m_pTextBuffer = NULL;
+      ResetView ();
+    }
+}
+
+int CCrystalTextView::
+GetScreenLines ()
+{
+  if (m_nScreenLines == -1)
+    {
+      CRect rect;
+      GetClientRect (&rect);
+      m_nScreenLines = rect.Height () / GetLineHeight ();
+    }
+  return m_nScreenLines;
+}
+
+BOOL CCrystalTextView::
+GetItalic (int nColorIndex)
+{
+  return nColorIndex == COLORINDEX_COMMENT;
+  //  return FALSE;
+}
+
+BOOL CCrystalTextView::
+GetBold (int nColorIndex)
+{
+  return nColorIndex == COLORINDEX_KEYWORD;
+  //  return FALSE;
+}
+
+int CCrystalTextView::
+GetScreenChars ()
+{
+  if (m_nScreenChars == -1)
+    {
+      CRect rect;
+      GetClientRect (&rect);
+      m_nScreenChars = (rect.Width () - GetMarginWidth ()) / GetCharWidth ();
+    }
+  return m_nScreenChars;
+}
+
+void CCrystalTextView::
+OnDestroy ()
+{
+  GetFont ()->GetLogFont (&m_lfBaseFont);
+  DetachFromBuffer ();
+  m_hAccel = NULL;
+
+  CView::OnDestroy ();
+
+  for (int I = 0; I < 4; I++)
+    {
+      if (m_apFonts[I] != NULL)
+        {
+          m_apFonts[I]->DeleteObject ();
+          delete m_apFonts[I];
+          m_apFonts[I] = NULL;
+        }
+    }
+  if (m_pCacheBitmap != NULL)
+    {
+      delete m_pCacheBitmap;
+      m_pCacheBitmap = NULL;
+    }
+}
+
+BOOL CCrystalTextView::
+OnEraseBkgnd (CDC * pdc)
+{
+  return TRUE;
+}
+
+void CCrystalTextView::
+OnSize (UINT nType, int cx, int cy)
+{
+  CView::OnSize (nType, cx, cy);
+
+       //BEGIN SW
+       // get char position of top left visible character with old cached word wrap
+       CPoint  topPos;
+       SubLineCursorPosToTextPos( CPoint( 0, m_nTopSubLine ), topPos );
+       //END SW
+
+  if (m_pCacheBitmap != NULL)
+    {
+      m_pCacheBitmap->DeleteObject ();
+      delete m_pCacheBitmap;
+      m_pCacheBitmap = NULL;
+    }
+  m_nScreenLines = -1;
+  m_nScreenChars = -1;
+
+       //BEGIN SW
+       // we have to recompute the line wrapping
+       InvalidateLineCache( 0, -1 );
+
+       // compute new top sub line
+       CPoint  topSubLine;
+       CharPosToPoint( topPos.y, topPos.x, topSubLine );
+       m_nTopSubLine = topPos.y + topSubLine.y;
+
+       // set caret to right position
+       UpdateCaret();
+       //END SW
+
+  RecalcVertScrollBar ();
+  RecalcHorzScrollBar ();
+  PostMessage (WM_COMMAND, ID_FORCE_REDRAW);
+}
+
+void CCrystalTextView::
+UpdateSiblingScrollPos (BOOL bHorz)
+{
+  CSplitterWnd *pSplitterWnd = GetParentSplitter (this, FALSE);
+  if (pSplitterWnd != NULL)
+    {
+      //  See CSplitterWnd::IdFromRowCol() implementation for details
+      int nCurrentRow = (GetDlgCtrlID () - AFX_IDW_PANE_FIRST) / 16;
+      int nCurrentCol = (GetDlgCtrlID () - AFX_IDW_PANE_FIRST) % 16;
+      ASSERT (nCurrentRow >= 0 && nCurrentRow < pSplitterWnd->GetRowCount ());
+      ASSERT (nCurrentCol >= 0 && nCurrentCol < pSplitterWnd->GetColumnCount ());
+
+      if (bHorz)
+         {
+          int nCols = pSplitterWnd->GetColumnCount ();
+          for (int nCol = 0; nCol < nCols; nCol++)
+                 {
+              if (nCol != nCurrentCol)  //  We don't need to update ourselves
+                         {
+                                 CCrystalTextView *pSiblingView = GetSiblingView (nCurrentRow, nCol);
+                                 if (pSiblingView != NULL)
+                                         pSiblingView->OnUpdateSibling (this, FALSE);
+                         }
+                 }
+         }
+      else
+         {
+          int nRows = pSplitterWnd->GetRowCount ();
+          for (int nRow = 0; nRow < nRows; nRow++)
+                 {
+              if (nRow != nCurrentRow)  //  We don't need to update ourselves
+                         {
+                                 CCrystalTextView *pSiblingView = GetSiblingView (nRow, nCurrentCol);
+                                 if (pSiblingView != NULL)
+                                         pSiblingView->OnUpdateSibling (this, FALSE);
+                         }
+                 }
+         }
+         
+
+    }
+}
+
+void CCrystalTextView::
+OnUpdateSibling (CCrystalTextView * pUpdateSource, BOOL bHorz)
+{
+  if (pUpdateSource != this)
+    {
+      ASSERT (pUpdateSource != NULL);
+      ASSERT_KINDOF (CCrystalTextView, pUpdateSource);
+      if (bHorz)
+        {
+          ASSERT (pUpdateSource->m_nTopLine >= 0);
+          ASSERT (pUpdateSource->m_nTopLine < GetLineCount ());
+          if (pUpdateSource->m_nTopLine != m_nTopLine)
+            {
+              ScrollToLine (pUpdateSource->m_nTopLine, TRUE, FALSE);
+              UpdateCaret ();
+            }
+        }
+      else
+        {
+          ASSERT (pUpdateSource->m_nOffsetChar >= 0);
+          ASSERT (pUpdateSource->m_nOffsetChar < GetMaxLineLength ());
+          if (pUpdateSource->m_nOffsetChar != m_nOffsetChar)
+            {
+              ScrollToChar (pUpdateSource->m_nOffsetChar, TRUE, FALSE);
+              UpdateCaret ();
+            }
+        }
+    }
+}
+
+void CCrystalTextView::
+RecalcVertScrollBar (BOOL bPositionOnly /*= FALSE*/ )
+{
+  SCROLLINFO si;
+  si.cbSize = sizeof (si);
+  if (bPositionOnly)
+    {
+      si.fMask = SIF_POS;
+               //BEGIN SW
+               si.nPos = m_nTopSubLine;
+               /*ORIGINAL
+               si.nPos = m_nTopLine;
+               */
+               //END SW
+    }
+  else
+    {
+               //BEGIN SW
+               if( GetScreenLines() >= GetSubLineCount() && m_nTopSubLine > 0 )
+               /*ORIGINAL
+               if (GetScreenLines() >= GetLineCount() && m_nTopLine > 0)
+               */
+               //END SW
+        {
+          m_nTopLine = 0;
+          Invalidate ();
+          UpdateCaret ();
+        }
+      si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
+      si.nMin = 0;
+               //BEGIN SW
+               si.nMax = GetSubLineCount() - 1;
+               /*ORIGINAL
+               si.nMax = GetLineCount() - 1;
+               */
+               //END SW
+      si.nPage = GetScreenLines ();
+               //BEGIN SW
+               si.nPos = m_nTopSubLine;
+               /*ORIGINAL
+               si.nPos = m_nTopLine;
+               */
+               //END SW
+    }
+  VERIFY (SetScrollInfo (SB_VERT, &si));
+}
+
+void CCrystalTextView::
+OnVScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar)
+{
+  CView::OnVScroll (nSBCode, nPos, pScrollBar);
+
+  //  Note we cannot use nPos because of its 16-bit nature
+  SCROLLINFO si;
+  si.cbSize = sizeof (si);
+  si.fMask = SIF_ALL;
+  VERIFY (GetScrollInfo (SB_VERT, &si));
+
+       //BEGIN SW
+       int nPageLines = GetScreenLines();
+       int nSubLineCount = GetSubLineCount();
+
+       int nNewTopSubLine;
+       BOOL bDisableSmooth = TRUE;
+       switch (nSBCode)
+       {
+       case SB_TOP:
+               nNewTopSubLine = 0;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_BOTTOM:
+               nNewTopSubLine = nSubLineCount - nPageLines + 1;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_LINEUP:
+               nNewTopSubLine = m_nTopSubLine - 1;
+               break;
+       case SB_LINEDOWN:
+               nNewTopSubLine = m_nTopSubLine + 1;
+               break;
+       case SB_PAGEUP:
+               nNewTopSubLine = m_nTopSubLine - si.nPage + 1;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_PAGEDOWN:
+               nNewTopSubLine = m_nTopSubLine + si.nPage - 1;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_THUMBPOSITION:
+       case SB_THUMBTRACK:
+               nNewTopSubLine = si.nTrackPos;
+               break;
+       default:
+               return;
+       }
+
+       if (nNewTopSubLine < 0)
+               nNewTopSubLine = 0;
+       if (nNewTopSubLine >= nSubLineCount)
+               nNewTopSubLine = nSubLineCount - 1;
+       ScrollToSubLine(nNewTopSubLine, bDisableSmooth);
+
+       /*ORIGINAL
+       int nPageLines = GetScreenLines();
+       int nLineCount = GetLineCount();
+
+       int nNewTopLine;
+       BOOL bDisableSmooth = TRUE;
+       switch (nSBCode)
+       {
+       case SB_TOP:
+               nNewTopLine = 0;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_BOTTOM:
+               nNewTopLine = nLineCount - nPageLines + 1;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_LINEUP:
+               nNewTopLine = m_nTopLine - 1;
+               break;
+       case SB_LINEDOWN:
+               nNewTopLine = m_nTopLine + 1;
+               break;
+       case SB_PAGEUP:
+               nNewTopLine = m_nTopLine - si.nPage + 1;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_PAGEDOWN:
+               nNewTopLine = m_nTopLine + si.nPage - 1;
+               bDisableSmooth = FALSE;
+               break;
+       case SB_THUMBPOSITION:
+       case SB_THUMBTRACK:
+               nNewTopLine = si.nTrackPos;
+               break;
+       default:
+               return;
+       }
+
+       if (nNewTopLine < 0)
+               nNewTopLine = 0;
+       if (nNewTopLine >= nLineCount)
+               nNewTopLine = nLineCount - 1;
+       ScrollToLine(nNewTopLine, bDisableSmooth);
+       *///END SW
+}
+
+void CCrystalTextView::
+RecalcHorzScrollBar (BOOL bPositionOnly /*= FALSE*/ )
+{
+  //  Again, we cannot use nPos because it's 16-bit
+  SCROLLINFO si;
+  si.cbSize = sizeof (si);
+  if (bPositionOnly)
+    {
+      si.fMask = SIF_POS;
+      si.nPos = m_nOffsetChar;
+    }
+  else
+    {
+      if (GetScreenChars () >= GetMaxLineLength () && m_nOffsetChar > 0)
+        {
+          m_nOffsetChar = 0;
+          Invalidate ();
+          UpdateCaret ();
+        }
+      si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
+      si.nMin = 0;
+      si.nMax = GetMaxLineLength () - 1;
+      si.nPage = GetScreenChars ();
+      si.nPos = m_nOffsetChar;
+    }
+  VERIFY (SetScrollInfo (SB_HORZ, &si));
+}
+
+void CCrystalTextView::
+OnHScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar)
+{
+  CView::OnHScroll (nSBCode, nPos, pScrollBar);
+
+  SCROLLINFO si;
+  si.cbSize = sizeof (si);
+  si.fMask = SIF_ALL;
+  VERIFY (GetScrollInfo (SB_HORZ, &si));
+
+  int nPageChars = GetScreenChars ();
+  int nMaxLineLength = GetMaxLineLength ();
+
+  int nNewOffset;
+  switch (nSBCode)
+    {
+    case SB_LEFT:
+      nNewOffset = 0;
+      break;
+    case SB_BOTTOM:
+      nNewOffset = nMaxLineLength - nPageChars + 1;
+      break;
+    case SB_LINEUP:
+      nNewOffset = m_nOffsetChar - 1;
+      break;
+    case SB_LINEDOWN:
+      nNewOffset = m_nOffsetChar + 1;
+      break;
+    case SB_PAGEUP:
+      nNewOffset = m_nOffsetChar - si.nPage + 1;
+      break;
+    case SB_PAGEDOWN:
+      nNewOffset = m_nOffsetChar + si.nPage - 1;
+      break;
+    case SB_THUMBPOSITION:
+    case SB_THUMBTRACK:
+      nNewOffset = si.nTrackPos;
+      break;
+    default:
+      return;
+    }
+
+  if (nNewOffset >= nMaxLineLength)
+    nNewOffset = nMaxLineLength - 1;
+  if (nNewOffset < 0)
+    nNewOffset = 0;
+  ScrollToChar (nNewOffset, TRUE);
+  UpdateCaret ();
+}
+
+BOOL CCrystalTextView::
+OnSetCursor (CWnd * pWnd, UINT nHitTest, UINT message)
+{
+  if (nHitTest == HTCLIENT)
+    {
+      CPoint pt;
+      ::GetCursorPos (&pt);
+      ScreenToClient (&pt);
+      if (pt.x < GetMarginWidth ())
+        {
+          ::SetCursor (::LoadCursor (GetResourceHandle (), MAKEINTRESOURCE (IDR_MARGIN_CURSOR)));
+        }
+      else
+        {
+          CPoint ptText = ClientToText (pt);
+          PrepareSelBounds ();
+          if (IsInsideSelBlock (ptText))
+            {
+              //  [JRT]:  Support For Disabling Drag and Drop...
+              if (!m_bDisableDragAndDrop)   // If Drag And Drop Not Disabled
+
+                ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE (IDC_ARROW)));     // Set To Arrow Cursor
+
+            }
+          else
+            ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE (IDC_IBEAM)));
+        }
+      return TRUE;
+    }
+  return CView::OnSetCursor (pWnd, nHitTest, message);
+}
+
+CPoint CCrystalTextView::
+ClientToText (const CPoint & point)
+{
+       //BEGIN SW
+       int nSubLineCount = GetSubLineCount();
+       int nLineCount = GetLineCount();
+
+       CPoint pt;
+       pt.y = m_nTopSubLine + point.y / GetLineHeight();
+       if (pt.y >= nSubLineCount)
+               pt.y = nSubLineCount - 1;
+       if (pt.y < 0)
+               pt.y = 0;
+
+       int nLine;
+       int nSubLineOffset;
+       int nOffsetChar = m_nOffsetChar;
+
+       GetLineBySubLine( pt.y, nLine, nSubLineOffset );
+       pt.y = nLine;
+
+       LPCTSTR pszLine = NULL;
+       int     nLength = 0;
+       int *anBreaks = NULL;
+       int     nBreaks = 0;
+
+       if (pt.y >= 0 && pt.y < nLineCount)
+       {
+               nLength = GetLineLength( pt.y );
+               anBreaks = (int*)_alloca( sizeof( int ) * nLength );
+               pszLine = GetLineChars(pt.y);
+               WrapLineCached( pt.y, GetScreenChars(), anBreaks, nBreaks );
+
+               if( nSubLineOffset > 0 )
+                       nOffsetChar = anBreaks[nSubLineOffset - 1];
+               if( nBreaks > nSubLineOffset )
+                       nLength = anBreaks[nSubLineOffset] - 1;
+       }
+
+       int nPos = nOffsetChar + (point.x - GetMarginWidth()) / GetCharWidth();
+       if (nPos < 0)
+               nPos = 0;
+
+       int nIndex = 0, nCurPos = 0, n = 0, i = 0;
+       int nTabSize = GetTabSize();
+
+       /*
+       if( m_bWordWrap )
+               nCurPos = nIndex = nOffsetChar;
+       */
+
+       while (nIndex < nLength)
+       {
+               if( nBreaks && nIndex == anBreaks[i] )
+               {
+                       n = nIndex;
+                       i++;
+               }
+
+               if (pszLine[nIndex] == _T('\t'))
+               {
+                       n+= (nTabSize - nCurPos % nTabSize);
+                       nCurPos += (nTabSize - nCurPos % nTabSize);
+               }
+               else
+               {
+                       n++;
+                       nCurPos ++;
+               }
+
+               if (n > nPos && i == nSubLineOffset)
+                       break;
+
+               nIndex ++;
+       }
+
+       ASSERT(nIndex >= 0 && nIndex <= nLength);
+       pt.x = nIndex;
+       return pt;
+
+       /*ORIGINAL
+       int nLineCount = GetLineCount();
+
+       CPoint pt;
+       pt.y = m_nTopLine + point.y / GetLineHeight();
+       if (pt.y >= nLineCount)
+               pt.y = nLineCount - 1;
+       if (pt.y < 0)
+               pt.y = 0;
+
+       int nLength = 0;
+       LPCTSTR pszLine = NULL;
+       if (pt.y >= 0 && pt.y < nLineCount)
+       {
+               nLength = GetLineLength(pt.y);
+               pszLine = GetLineChars(pt.y);
+       }
+
+       int nPos = m_nOffsetChar + (point.x - GetMarginWidth()) / GetCharWidth();
+       if (nPos < 0)
+               nPos = 0;
+
+       int nIndex = 0, nCurPos = 0;
+       int nTabSize = GetTabSize();
+       while (nIndex < nLength)
+       {
+               if (pszLine[nIndex] == _T('\t'))
+                       nCurPos += (nTabSize - nCurPos % nTabSize);
+               else
+                       nCurPos ++;
+
+               if (nCurPos > nPos)
+                       break;
+
+               nIndex ++;
+       }
+
+       ASSERT(nIndex >= 0 && nIndex <= nLength);
+       pt.x = nIndex;
+       return pt;
+       *///END SW
+}
+
+#ifdef _DEBUG
+void CCrystalTextView::
+AssertValidTextPos (const CPoint & point)
+{
+  if (GetLineCount () > 0)
+    {
+      ASSERT (m_nTopLine >= 0 && m_nOffsetChar >= 0);
+      ASSERT (point.y >= 0 && point.y < GetLineCount ());
+      ASSERT (point.x >= 0 && point.x <= GetLineLength (point.y));
+    }
+}
+#endif
+
+bool CCrystalTextView::
+IsValidTextPos (const CPoint &point)
+{
+  return GetLineCount () > 0 && m_nTopLine >= 0 && m_nOffsetChar >= 0 &&
+    point.y >= 0 && point.y < GetLineCount () && point.x >= 0 && point.x <= GetLineLength (point.y);
+}
+
+bool CCrystalTextView::
+IsValidTextPosX (const CPoint &point)
+{
+  return GetLineCount () > 0 && m_nTopLine >= 0 && m_nOffsetChar >= 0 &&
+    point.y >= 0 && point.y < GetLineCount () && point.x >= 0 && point.x <= GetLineLength (point.y);
+}
+
+bool CCrystalTextView::
+IsValidTextPosY (const CPoint &point)
+{
+  return GetLineCount () > 0 && m_nTopLine >= 0 && m_nOffsetChar >= 0 &&
+    point.y >= 0 && point.y < GetLineCount ();
+}
+
+CPoint CCrystalTextView::
+TextToClient (const CPoint & point)
+{
+  ASSERT_VALIDTEXTPOS (point);
+  LPCTSTR pszLine = GetLineChars (point.y);
+
+  CPoint pt;
+       //BEGIN SW
+       CPoint  charPoint;
+       int                     nSubLineStart = CharPosToPoint( point.y, point.x, charPoint );
+       charPoint.y+= GetSubLineIndex( point.y );
+
+       // compute y-position
+       pt.y = (charPoint.y - m_nTopSubLine) * GetLineHeight();
+
+       // if pt.x is null, we know the result
+       if( charPoint.x == 0 )
+       {
+               pt.x = GetMarginWidth();
+               return pt;
+       }
+
+       // we have to calculate x-position
+       int     nPreOffset = 0;
+       /*ORIGINAL
+       pt.y = (point.y - m_nTopLine) * GetLineHeight();
+       */
+       //END SW
+  pt.x = 0;
+  int nTabSize = GetTabSize ();
+  for (int nIndex = 0; nIndex < point.x; nIndex++)
+    {
+               //BEGIN SW
+               if( nIndex == nSubLineStart )
+                       nPreOffset = pt.x;
+               //END SW
+      if (pszLine[nIndex] == _T ('\t'))
+        pt.x += (nTabSize - pt.x % nTabSize);
+      else
+        pt.x++;
+    }
+       //BEGIN SW
+       pt.x-= nPreOffset;
+       //END SW
+
+  pt.x = (pt.x - m_nOffsetChar) * GetCharWidth () + GetMarginWidth ();
+  return pt;
+}
+
+void CCrystalTextView::
+InvalidateLines (int nLine1, int nLine2, BOOL bInvalidateMargin /*= FALSE*/ )
+{
+  bInvalidateMargin = TRUE;
+  if (nLine2 == -1)
+    {
+      CRect rcInvalid;
+      GetClientRect (&rcInvalid);
+      if (!bInvalidateMargin)
+        rcInvalid.left += GetMarginWidth ();
+               //BEGIN SW
+               rcInvalid.top = (GetSubLineIndex( nLine1 ) - m_nTopSubLine) * GetLineHeight();
+               /*ORIGINAL
+               rcInvalid.top = (nLine1 - m_nTopLine) * GetLineHeight();
+               */
+               //END SW
+      InvalidateRect (&rcInvalid, FALSE);
+    }
+  else
+    {
+      if (nLine2 < nLine1)
+        {
+          int nTemp = nLine1;
+          nLine1 = nLine2;
+          nLine2 = nTemp;
+        }
+      CRect rcInvalid;
+      GetClientRect (&rcInvalid);
+      if (!bInvalidateMargin)
+        rcInvalid.left += GetMarginWidth ();
+               //BEGIN SW
+               rcInvalid.top = (GetSubLineIndex( nLine1 ) - m_nTopSubLine) * GetLineHeight();
+               rcInvalid.bottom = (GetSubLineIndex( nLine2 ) - m_nTopSubLine + GetSubLines( nLine2 )) * GetLineHeight();
+               /*ORIGINAL
+               rcInvalid.top = (nLine1 - m_nTopLine) * GetLineHeight();
+               rcInvalid.bottom = (nLine2 - m_nTopLine + 1) * GetLineHeight();
+               */
+               //END SW
+      InvalidateRect (&rcInvalid, FALSE);
+    }
+}
+
+void CCrystalTextView::
+SetSelection (const CPoint & ptStart, const CPoint & ptEnd)
+{
+  ASSERT_VALIDTEXTPOS (ptStart);
+  ASSERT_VALIDTEXTPOS (ptEnd);
+  if (m_ptSelStart == ptStart)
+    {
+      if (m_ptSelEnd != ptEnd)
+        InvalidateLines (ptEnd.y, m_ptSelEnd.y);
+    }
+  else
+    {
+      InvalidateLines (ptStart.y, ptEnd.y);
+      InvalidateLines (m_ptSelStart.y, m_ptSelEnd.y);
+    }
+  m_ptSelStart = ptStart;
+  m_ptSelEnd = ptEnd;
+}
+
+void CCrystalTextView::
+AdjustTextPoint (CPoint & point)
+{
+  point.x += GetCharWidth () / 2;   //todo
+
+}
+
+void CCrystalTextView::
+OnSetFocus (CWnd * pOldWnd)
+{
+  CView::OnSetFocus (pOldWnd);
+
+  m_bFocused = TRUE;
+  if (m_ptSelStart != m_ptSelEnd)
+    InvalidateLines (m_ptSelStart.y, m_ptSelEnd.y);
+  UpdateCaret ();
+}
+
+DWORD CCrystalTextView::
+ParseLinePlain (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  return 0;
+}
+
+DWORD CCrystalTextView::
+ParseLine (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  return (this->*(m_CurSourceDef->ParseLineX)) (dwCookie, nLineIndex, pBuf, nActualItems);
+}
+
+int CCrystalTextView::
+CalculateActualOffset (int nLineIndex, int nCharIndex)
+{
+  int nLength = GetLineLength (nLineIndex);
+  ASSERT (nCharIndex >= 0 && nCharIndex <= nLength);
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  int nOffset = 0;
+  int nTabSize = GetTabSize ();
+       //BEGIN SW
+       int                     *anBreaks = (int*)_alloca( sizeof( int ) * nLength );
+       int                     nBreaks = 0;
+
+       /*if( nLength > GetScreenChars() )*/
+       WrapLineCached( nLineIndex, GetScreenChars(), anBreaks, nBreaks );
+
+       int     nPreOffset = 0;
+       int     nPreBreak = 0;
+
+       if( nBreaks )
+       {
+               for( int J = nBreaks - 1; J >= 0 && nCharIndex < anBreaks[J]; J-- );
+               nPreBreak = anBreaks[J];
+       }
+       //END SW
+  for (int I = 0; I < nCharIndex; I++)
+    {
+               //BEGIN SW
+               if( nPreBreak == I && nBreaks )
+                       nPreOffset = nOffset;
+               //END SW
+      if (pszChars[I] == _T ('\t'))
+        nOffset += (nTabSize - nOffset % nTabSize);
+      else
+        nOffset++;
+    }
+       //BEGIN SW
+       if( nPreBreak == I && nBreaks )
+               return 0;
+       else
+               return nOffset - nPreOffset;
+       /*ORIGINAL
+       return nOffset;
+       *///END SW
+}
+
+int CCrystalTextView::
+ApproxActualOffset (int nLineIndex, int nOffset)
+{
+  if (nOffset == 0)
+    return 0;
+
+  int nLength = GetLineLength (nLineIndex);
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  int nCurrentOffset = 0;
+  int nTabSize = GetTabSize ();
+  for (int I = 0; I < nLength; I++)
+    {
+      if (pszChars[I] == _T ('\t'))
+        nCurrentOffset += (nTabSize - nCurrentOffset % nTabSize);
+      else
+        nCurrentOffset++;
+      if (nCurrentOffset >= nOffset)
+        {
+          if (nOffset <= nCurrentOffset - nTabSize / 2)
+            return I;
+          return I + 1;
+        }
+    }
+  return nLength;
+}
+
+void CCrystalTextView::
+EnsureVisible (CPoint pt)
+{
+  //  Scroll vertically
+       //BEGIN SW
+       int                     nSubLineCount = GetSubLineCount();
+       int                     nNewTopSubLine = m_nTopSubLine;
+       CPoint  subLinePos;
+
+       CharPosToPoint( pt.y, pt.x, subLinePos );
+       subLinePos.y+= GetSubLineIndex( pt.y );
+
+       if( subLinePos.y >= nNewTopSubLine + GetScreenLines() )
+               nNewTopSubLine = subLinePos.y - GetScreenLines() + 1;
+       if( subLinePos.y < nNewTopSubLine )
+               nNewTopSubLine = subLinePos.y;
+
+       if( nNewTopSubLine < 0 )
+               nNewTopSubLine = 0;
+       if( nNewTopSubLine >= nSubLineCount )
+               nNewTopSubLine = nSubLineCount - 1;
+       
+       if( nNewTopSubLine != m_nTopSubLine )
+       {
+               ScrollToSubLine( nNewTopSubLine );
+               UpdateCaret();
+               UpdateSiblingScrollPos( FALSE );
+       }
+       /*ORIGINAL
+       int nLineCount = GetLineCount();
+       int nNewTopLine = m_nTopLine;
+       if (pt.y >= nNewTopLine + GetScreenLines())
+       {
+               nNewTopLine = pt.y - GetScreenLines() + 1;
+       }
+       if (pt.y < nNewTopLine)
+       {
+               nNewTopLine = pt.y;
+       }
+
+       if (nNewTopLine < 0)
+               nNewTopLine = 0;
+       if (nNewTopLine >= nLineCount)
+               nNewTopLine = nLineCount - 1;
+
+       if (m_nTopLine != nNewTopLine)
+       {
+               ScrollToLine(nNewTopLine);
+               UpdateSiblingScrollPos(TRUE);
+       }
+       */
+       //END SW
+
+  //  Scroll horizontally
+       //BEGIN SW
+       // we do not need horizontally scrolling, if we wrap the words
+       if( m_bWordWrap )
+               return;
+       //END SW
+  int nActualPos = CalculateActualOffset (pt.y, pt.x);
+  int nNewOffset = m_nOffsetChar;
+  if (nActualPos > nNewOffset + GetScreenChars ())
+    {
+      nNewOffset = nActualPos - GetScreenChars ();
+    }
+  if (nActualPos < nNewOffset)
+    {
+      nNewOffset = nActualPos;
+    }
+
+  if (nNewOffset >= GetMaxLineLength ())
+    nNewOffset = GetMaxLineLength () - 1;
+  if (nNewOffset < 0)
+    nNewOffset = 0;
+
+  if (m_nOffsetChar != nNewOffset)
+    {
+      ScrollToChar (nNewOffset);
+      UpdateCaret ();
+      UpdateSiblingScrollPos (TRUE);
+    }
+}
+
+void CCrystalTextView::
+OnKillFocus (CWnd * pNewWnd)
+{
+  CView::OnKillFocus (pNewWnd);
+
+  m_bFocused = FALSE;
+  UpdateCaret ();
+  if (m_ptSelStart != m_ptSelEnd)
+    InvalidateLines (m_ptSelStart.y, m_ptSelEnd.y);
+  if (m_bDragSelection)
+    {
+      ReleaseCapture ();
+      KillTimer (m_nDragSelTimer);
+      m_bDragSelection = FALSE;
+    }
+}
+
+void CCrystalTextView::
+OnSysColorChange ()
+{
+  CView::OnSysColorChange ();
+  Invalidate ();
+}
+
+void CCrystalTextView::
+GetText (const CPoint & ptStart, const CPoint & ptEnd, CString & text)
+{
+  if (m_pTextBuffer != NULL)
+    m_pTextBuffer->GetText (ptStart.y, ptStart.x, ptEnd.y, ptEnd.x, text);
+  else
+    text = _T ("");
+}
+
+void CCrystalTextView::
+UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext,
+            DWORD dwFlags, int nLineIndex /*= -1*/ )
+{
+  // SetTextType (GetExt (GetDocument ()->GetPathName ()));
+  if (dwFlags & UPDATE_RESET)
+    {
+      ResetView ();
+      RecalcVertScrollBar ();
+      RecalcHorzScrollBar ();
+      return;
+    }
+
+  int nLineCount = GetLineCount ();
+  ASSERT (nLineCount > 0);
+  ASSERT (nLineIndex >= -1 && nLineIndex < nLineCount);
+  if ((dwFlags & UPDATE_SINGLELINE) != 0)
+    {
+      ASSERT (nLineIndex != -1);
+      //  All text below this line should be reparsed
+      if (m_pdwParseCookies != NULL)
+        {
+          ASSERT (m_nParseArraySize == nLineCount);
+          memset (m_pdwParseCookies + nLineIndex, 0xff, sizeof (DWORD) * (m_nParseArraySize - nLineIndex));
+        }
+      //  This line'th actual length must be recalculated
+      if (m_pnActualLineLength != NULL)
+        {
+          ASSERT (m_nActualLengthArraySize == nLineCount);
+          m_pnActualLineLength[nLineIndex] = -1;
+                       //BEGIN SW
+                       InvalidateLineCache( nLineIndex, nLineIndex );
+                       //END SW
+        }
+      //  Repaint the lines
+      InvalidateLines (nLineIndex, -1, TRUE);
+    }
+  else
+    {
+      if (nLineIndex == -1)
+        nLineIndex = 0;         //  Refresh all text
+      //  All text below this line should be reparsed
+
+      if (m_pdwParseCookies != NULL)
+        {
+          if (m_nParseArraySize != nLineCount)
+            {
+              //  Reallocate cookies array
+              DWORD *pdwNewArray = new DWORD[nLineCount];
+              if (nLineIndex > 0)
+                memcpy (pdwNewArray, m_pdwParseCookies, sizeof (DWORD) * nLineIndex);
+              delete m_pdwParseCookies;
+              m_nParseArraySize = nLineCount;
+              m_pdwParseCookies = pdwNewArray;
+            }
+          memset (m_pdwParseCookies + nLineIndex, 0xff, sizeof (DWORD) * (m_nParseArraySize - nLineIndex));
+        }
+      //  Recalculate actual length for all lines below this
+      if (m_pnActualLineLength != NULL)
+        {
+          if (m_nActualLengthArraySize != nLineCount)
+            {
+              //  Reallocate actual length array
+              int *pnNewArray = new int[nLineCount];
+              if (nLineIndex > 0)
+                memcpy (pnNewArray, m_pnActualLineLength, sizeof (int) * nLineIndex);
+              delete m_pnActualLineLength;
+              m_nActualLengthArraySize = nLineCount;
+              m_pnActualLineLength = pnNewArray;
+            }
+          memset (m_pnActualLineLength + nLineIndex, 0xff, sizeof (DWORD) * (m_nActualLengthArraySize - nLineIndex));
+        }
+               //BEGIN SW
+               InvalidateLineCache( nLineIndex, -1 );
+               //END SW
+      //  Repaint the lines
+      InvalidateLines (nLineIndex, -1, TRUE);
+    }
+
+  //  All those points must be recalculated and validated
+  if (pContext != NULL)
+    {
+      pContext->RecalcPoint (m_ptCursorPos);
+      pContext->RecalcPoint (m_ptSelStart);
+      pContext->RecalcPoint (m_ptSelEnd);
+      pContext->RecalcPoint (m_ptAnchor);
+      ASSERT_VALIDTEXTPOS (m_ptCursorPos);
+      ASSERT_VALIDTEXTPOS (m_ptSelStart);
+      ASSERT_VALIDTEXTPOS (m_ptSelEnd);
+      ASSERT_VALIDTEXTPOS (m_ptAnchor);
+      if (m_bDraggingText)
+        {
+          pContext->RecalcPoint (m_ptDraggedTextBegin);
+          pContext->RecalcPoint (m_ptDraggedTextEnd);
+          ASSERT_VALIDTEXTPOS (m_ptDraggedTextBegin);
+          ASSERT_VALIDTEXTPOS (m_ptDraggedTextEnd);
+        }
+      CPoint ptTopLine (0, m_nTopLine);
+      pContext->RecalcPoint (ptTopLine);
+      ASSERT_VALIDTEXTPOS (ptTopLine);
+      m_nTopLine = ptTopLine.y;
+      UpdateCaret ();
+    }
+
+  //  Recalculate vertical scrollbar, if needed
+  if ((dwFlags & UPDATE_VERTRANGE) != 0)
+    {
+      if (!m_bVertScrollBarLocked)
+        RecalcVertScrollBar ();
+    }
+
+  //  Recalculate horizontal scrollbar, if needed
+  if ((dwFlags & UPDATE_HORZRANGE) != 0)
+    {
+      m_nMaxLineLength = -1;
+      if (!m_bHorzScrollBarLocked)
+        RecalcHorzScrollBar ();
+    }
+}
+
+HINSTANCE CCrystalTextView::
+GetResourceHandle ()
+{
+#ifdef CRYSEDIT_RES_HANDLE
+  return CRYSEDIT_RES_HANDLE;
+#else
+  if (s_hResourceInst != NULL)
+    return s_hResourceInst;
+  return AfxGetResourceHandle ();
+#endif
+}
+
+int CCrystalTextView::
+OnCreate (LPCREATESTRUCT lpCreateStruct)
+{
+  memset (&m_lfBaseFont, 0, sizeof (m_lfBaseFont));
+  _tcscpy (m_lfBaseFont.lfFaceName, _T ("FixedSys"));
+  m_lfBaseFont.lfHeight = 0;
+  m_lfBaseFont.lfWeight = FW_NORMAL;
+  m_lfBaseFont.lfItalic = FALSE;
+  m_lfBaseFont.lfCharSet = DEFAULT_CHARSET;
+  m_lfBaseFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+  m_lfBaseFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+  m_lfBaseFont.lfQuality = DEFAULT_QUALITY;
+  m_lfBaseFont.lfPitchAndFamily = DEFAULT_PITCH;
+
+  if (CView::OnCreate (lpCreateStruct) == -1)
+    return -1;
+
+  /*TODO
+  ASSERT (m_hAccel == NULL);
+             // vvv GetResourceHandle () ???
+  HINSTANCE hInst = AfxFindResourceHandle (MAKEINTRESOURCE(IDR_DEFAULT_ACCEL), RT_ACCELERATOR);
+  ASSERT (hInst);
+  m_hAccel =::LoadAccelerators (hInst, MAKEINTRESOURCE (IDR_DEFAULT_ACCEL));
+  ASSERT (m_hAccel != NULL);*/
+  return 0;
+}
+
+void CCrystalTextView::
+SetAnchor (const CPoint & ptNewAnchor)
+{
+  ASSERT_VALIDTEXTPOS (ptNewAnchor);
+  m_ptAnchor = ptNewAnchor;
+}
+
+void CCrystalTextView::
+OnEditOperation (int nAction, LPCTSTR pszText)
+{
+}
+
+BOOL CCrystalTextView::
+PreTranslateMessage (MSG * pMsg)
+{
+  if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
+    {
+      if (m_hAccel != NULL)
+        {
+          if (::TranslateAccelerator (m_hWnd, m_hAccel, pMsg))
+            return TRUE;
+        }
+    }
+
+  return CView::PreTranslateMessage (pMsg);
+}
+
+CPoint CCrystalTextView::
+GetCursorPos ()
+{
+  return m_ptCursorPos;
+}
+
+void CCrystalTextView::
+SetCursorPos (const CPoint & ptCursorPos)
+{
+  ASSERT_VALIDTEXTPOS (ptCursorPos);
+  m_ptCursorPos = ptCursorPos;
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  UpdateCaret ();
+}
+
+void CCrystalTextView::
+SetSelectionMargin (BOOL bSelMargin)
+{
+  if (m_bSelMargin != bSelMargin)
+    {
+      m_bSelMargin = bSelMargin;
+      if (::IsWindow (m_hWnd))
+        {
+          m_nScreenChars = -1;
+          Invalidate ();
+          RecalcHorzScrollBar ();
+        }
+    }
+}
+
+void CCrystalTextView::
+GetFont (LOGFONT & lf)
+{
+  lf = m_lfBaseFont;
+}
+
+void CCrystalTextView::
+SetFont (const LOGFONT & lf)
+{
+  m_lfBaseFont = lf;
+  m_nScreenLines = -1;
+  m_nScreenChars = -1;
+  m_nCharWidth = -1;
+  m_nLineHeight = -1;
+  if (m_pCacheBitmap != NULL)
+    {
+      m_pCacheBitmap->DeleteObject ();
+      delete m_pCacheBitmap;
+      m_pCacheBitmap = NULL;
+    }
+  for (int I = 0; I < 4; I++)
+    {
+      if (m_apFonts[I] != NULL)
+        {
+          m_apFonts[I]->DeleteObject ();
+          delete m_apFonts[I];
+          m_apFonts[I] = NULL;
+        }
+    }
+  if (::IsWindow (m_hWnd))
+    {
+      RecalcVertScrollBar ();
+      RecalcHorzScrollBar ();
+      UpdateCaret ();
+      Invalidate ();
+    }
+}
+
+void CCrystalTextView::
+OnUpdateIndicatorPosition (CCmdUI * pCmdUI)
+{
+  ASSERT_VALIDTEXTPOS (m_ptCursorPos);
+  CString stat;
+                                                   // VVV m_ptCursorPos.x + 1 ???
+  stat.Format (_T ("Ln %d, Col %d"), m_ptCursorPos.y + 1, m_nIdealCharPos + 1);
+  pCmdUI->SetText (stat);
+       //BEGIN SW
+       if( pCmdUI->m_pOther && pCmdUI->m_pOther->IsKindOf( RUNTIME_CLASS(CStatusBar) ) )
+               OnUpdateStatusMessage( (CStatusBar*)pCmdUI->m_pOther );
+       //END SW
+}
+
+void CCrystalTextView::
+OnUpdateIndicatorCRLF (CCmdUI * pCmdUI)
+{
+  if (m_pTextBuffer != NULL)
+    {
+      int crlfMode = m_pTextBuffer->GetCRLFMode ();
+      switch (crlfMode)
+        {
+        case CRLF_STYLE_DOS:
+          pCmdUI->SetText (_T ("DOS"));
+          pCmdUI->Enable (TRUE);
+          break;
+        case CRLF_STYLE_UNIX:
+          pCmdUI->SetText (_T ("UNIX"));
+          pCmdUI->Enable (TRUE);
+          break;
+        case CRLF_STYLE_MAC:
+          pCmdUI->SetText (_T ("MAC"));
+          pCmdUI->Enable (TRUE);
+          break;
+        default:
+          pCmdUI->SetText (NULL);
+          pCmdUI->Enable (FALSE);
+        }
+    }
+  else
+    {
+      pCmdUI->SetText (NULL);
+      pCmdUI->Enable (FALSE);
+    }
+}
+
+void CCrystalTextView::
+OnToggleBookmark (UINT nCmdID)
+{
+  int nBookmarkID = nCmdID - ID_EDIT_TOGGLE_BOOKMARK0;
+  ASSERT (nBookmarkID >= 0 && nBookmarkID <= 9);
+  if (m_pTextBuffer != NULL)
+    {
+      DWORD dwFlags = GetLineFlags (m_ptCursorPos.y);
+      DWORD dwMask = LF_BOOKMARK (nBookmarkID);
+      m_pTextBuffer->SetLineFlag (m_ptCursorPos.y, dwMask, (dwFlags & dwMask) == 0);
+    }
+}
+
+void CCrystalTextView::
+OnGoBookmark (UINT nCmdID)
+{
+  int nBookmarkID = nCmdID - ID_EDIT_GO_BOOKMARK0;
+  ASSERT (nBookmarkID >= 0 && nBookmarkID <= 9);
+  if (m_pTextBuffer != NULL)
+    {
+      int nLine = m_pTextBuffer->GetLineWithFlag (LF_BOOKMARK (nBookmarkID));
+      if (nLine >= 0)
+        {
+          CPoint pt (0, nLine);
+          ASSERT_VALIDTEXTPOS (pt);
+          SetCursorPos (pt);
+          SetSelection (pt, pt);
+          SetAnchor (pt);
+          EnsureVisible (pt);
+        }
+    }
+}
+
+void CCrystalTextView::
+OnClearBookmarks ()
+{
+  if (m_pTextBuffer != NULL)
+    {
+      for (int nBookmarkID = 0; nBookmarkID <= 9; nBookmarkID++)
+        {
+          int nLine = m_pTextBuffer->GetLineWithFlag (LF_BOOKMARK (nBookmarkID));
+          if (nLine >= 0)
+            {
+              m_pTextBuffer->SetLineFlag (nLine, LF_BOOKMARK (nBookmarkID), FALSE);
+            }
+        }
+
+    }
+}
+
+void CCrystalTextView::
+ShowCursor ()
+{
+  m_bCursorHidden = FALSE;
+  UpdateCaret ();
+}
+
+void CCrystalTextView::
+HideCursor ()
+{
+  m_bCursorHidden = TRUE;
+  UpdateCaret ();
+}
+
+void CCrystalTextView::
+PopCursor ()
+{
+  if (IsValidTextPosY (m_ptCursorLast))
+    {
+      if (!IsValidTextPosX (m_ptCursorLast))
+        m_ptCursorLast.x = 0;
+      ASSERT_VALIDTEXTPOS (m_ptCursorLast);
+      CPoint ptCursorPos = m_ptCursorLast;
+      SetCursorPos (ptCursorPos);
+      SetSelection (ptCursorPos, ptCursorPos);
+      SetAnchor (ptCursorPos);
+      EnsureVisible (ptCursorPos);
+    }
+}
+
+void CCrystalTextView::
+PushCursor ()
+{
+  m_ptCursorLast = m_ptCursorPos;
+}
+
+DROPEFFECT CCrystalTextView::
+GetDropEffect ()
+{
+  return DROPEFFECT_COPY;
+}
+
+void CCrystalTextView::
+OnDropSource (DROPEFFECT de)
+{
+  ASSERT (de == DROPEFFECT_COPY);
+}
+
+HGLOBAL CCrystalTextView::
+PrepareDragData ()
+{
+  PrepareSelBounds ();
+  if (m_ptDrawSelStart == m_ptDrawSelEnd)
+    return NULL;
+
+  CString text;
+  GetText (m_ptDrawSelStart, m_ptDrawSelEnd, text);
+  HGLOBAL hData =::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, _tcslen (text) + 1);
+  if (hData == NULL)
+    return NULL;
+
+  LPTSTR pszData = (LPTSTR)::GlobalLock (hData);
+  _tcscpy (pszData, text.GetBuffer (0));
+  text.ReleaseBuffer ();
+  ::GlobalUnlock (hData);
+
+  m_ptDraggedTextBegin = m_ptDrawSelStart;
+  m_ptDraggedTextEnd = m_ptDrawSelEnd;
+  return hData;
+}
+
+static int
+FindStringHelper (LPCTSTR pszFindWhere, LPCTSTR pszFindWhat, DWORD dwFlags, int &nLen, RxNode *&rxnode, RxMatchRes *rxmatch)
+{
+  if (dwFlags & FIND_REGEXP)
+    {
+      int pos;
+
+      if (rxnode)
+        RxFree (rxnode);
+      rxnode = RxCompile (pszFindWhat);
+      if (rxnode && RxExec (rxnode, pszFindWhere, _tcslen (pszFindWhere), pszFindWhere, rxmatch, (dwFlags & FIND_MATCH_CASE) != 0 ? RX_CASE : 0))
+        {
+          pos = rxmatch->Open[0];
+          nLen = rxmatch->Close[0] - rxmatch->Open[0];
+        }
+      else
+        {
+          pos = -1;
+        }
+      return pos;
+    }
+  else
+    {
+      ASSERT (pszFindWhere != NULL);
+      ASSERT (pszFindWhat != NULL);
+      int nCur = 0;
+      int nLength = _tcslen (pszFindWhat);
+      nLen = nLength;
+      for (;;)
+        {
+          LPCTSTR pszPos = _tcsstr (pszFindWhere, pszFindWhat);
+          if (pszPos == NULL)
+            return -1;
+          if ((dwFlags & FIND_WHOLE_WORD) == 0)
+            return nCur + (pszPos - pszFindWhere);
+          if (pszPos > pszFindWhere && xisalnum (pszPos[-1]))
+            {
+              nCur += (pszPos - pszFindWhere);
+              pszFindWhere = pszPos + 1;
+              continue;
+            }
+          if (xisalnum (pszPos[nLength]))
+            {
+              nCur += (pszPos - pszFindWhere + 1);
+              pszFindWhere = pszPos + 1;
+              continue;
+            }
+          return nCur + (pszPos - pszFindWhere);
+        }
+    }
+  ASSERT (FALSE);               // Unreachable
+
+  return -1;
+}
+
+BOOL CCrystalTextView::
+HighlightText (const CPoint & ptStartPos, int nLength, BOOL bReverse /*= FALSE*/)
+{
+  ASSERT_VALIDTEXTPOS (ptStartPos);
+  CPoint ptEndPos = ptStartPos;
+  int nCount = GetLineLength (ptEndPos.y) - ptEndPos.x;
+  if (nLength <= nCount)
+    {
+      ptEndPos.x += nLength;
+    }
+  else
+    {
+      while (nLength > nCount)
+        {
+          nLength -= nCount + 1;
+          nCount = GetLineLength (++ptEndPos.y);
+        }
+      ptEndPos.x = nLength;
+    }
+  ASSERT_VALIDTEXTPOS (m_ptCursorPos);  //  Probably 'nLength' is bigger than expected...
+
+  m_ptCursorPos = bReverse ? ptStartPos : ptEndPos;
+  m_ptAnchor = m_ptCursorPos;
+  SetSelection (ptStartPos, ptEndPos);
+  UpdateCaret ();
+  EnsureVisible (m_ptCursorPos);
+  return TRUE;
+}
+
+BOOL CCrystalTextView::
+FindText (LPCTSTR pszText, const CPoint & ptStartPos, DWORD dwFlags,
+          BOOL bWrapSearch, CPoint * pptFoundPos)
+{
+  int nLineCount = GetLineCount ();
+  return FindTextInBlock (pszText, ptStartPos, CPoint (0, 0),
+                          CPoint (GetLineLength (nLineCount - 1), nLineCount - 1),
+                          dwFlags, bWrapSearch, pptFoundPos);
+}
+
+int HowManyStr (LPCTSTR s, LPCTSTR m)
+{
+  LPCTSTR p = s;
+  int n = 0, l = _tcslen (m);
+  while ((p = _tcsstr (p, m)) != NULL)
+    {
+      n++;
+      p += l;
+    }
+  return n;
+}
+
+int HowManyStr (LPCTSTR s, TCHAR c)
+{
+  LPCTSTR p = s;
+  int n = 0;
+  while ((p = _tcschr (p, c)) != NULL)
+    {
+      n++;
+      p++;
+    }
+  return n;
+}
+
+BOOL CCrystalTextView::
+FindTextInBlock (LPCTSTR pszText, const CPoint & ptStartPosition,
+                 const CPoint & ptBlockBegin, const CPoint & ptBlockEnd,
+                 DWORD dwFlags, BOOL bWrapSearch, CPoint * pptFoundPos)
+{
+  CPoint ptCurrentPos = ptStartPosition;
+
+  ASSERT (pszText != NULL && _tcslen (pszText) > 0);
+  ASSERT_VALIDTEXTPOS (ptCurrentPos);
+  ASSERT_VALIDTEXTPOS (ptBlockBegin);
+  ASSERT_VALIDTEXTPOS (ptBlockEnd);
+  ASSERT (ptBlockBegin.y < ptBlockEnd.y || ptBlockBegin.y == ptBlockEnd.y &&
+          ptBlockBegin.x <= ptBlockEnd.x);
+  if (ptBlockBegin == ptBlockEnd)
+    return FALSE;
+  CWaitCursor waitCursor;
+  if (ptCurrentPos.y < ptBlockBegin.y || ptCurrentPos.y == ptBlockBegin.y &&
+        ptCurrentPos.x < ptBlockBegin.x)
+    ptCurrentPos = ptBlockBegin;
+
+  CString what = pszText;
+  int nEolns;
+  if (dwFlags & FIND_REGEXP)
+    {
+      nEolns = HowManyStr (what, _T("\\n"));
+    }
+  else
+    {
+      nEolns = 0;
+      if ((dwFlags & FIND_MATCH_CASE) == 0)
+        what.MakeUpper ();
+    }
+  if (dwFlags & FIND_DIRECTION_UP)
+    {
+      //  Let's check if we deal with whole text.
+      //  At this point, we cannot search *up* in selection
+      ASSERT (ptBlockBegin.x == 0 && ptBlockBegin.y == 0);
+      ASSERT (ptBlockEnd.x == GetLineLength (GetLineCount () - 1) &&
+              ptBlockEnd.y == GetLineCount () - 1);
+
+      //  Proceed as if we have whole text search.
+      for (;;)
+        {
+          while (ptCurrentPos.y >= 0)
+            {
+              int nLineLength;
+              CString line;
+              if (dwFlags & FIND_REGEXP)
+                {
+                  for (int i = 0; i <= nEolns && ptCurrentPos.y >= i; i++)
+                    {
+                      CString item;
+                      LPCTSTR pszChars = GetLineChars (ptCurrentPos.y - i);
+                      if (i)
+                        {
+                          nLineLength = GetLineLength (ptCurrentPos.y - i);
+                          ptCurrentPos.x = 0;
+                          line = _T ('\n') + line;
+                        }
+                      else
+                        {
+                          nLineLength = ptCurrentPos.x != -1 ? ptCurrentPos.x : GetLineLength (ptCurrentPos.y - i);
+                        }
+                      if (nLineLength > 0)
+                        {
+                          LPTSTR pszBuf = item.GetBuffer (nLineLength + 1);
+                          _tcsncpy (pszBuf, pszChars, nLineLength);
+                          pszBuf[nLineLength] = _T ('\0');
+                          item.ReleaseBuffer ();
+                          line = item + line;
+                        }
+                    }
+                  nLineLength = line.GetLength ();
+                  if (ptCurrentPos.x == -1)
+                    ptCurrentPos.x = 0;
+                }
+              else
+                {
+                               nLineLength = GetLineLength(ptCurrentPos.y);
+                               //BEGIN SW+FP
+                  if (ptCurrentPos.x == -1)
+                    {
+                      ptCurrentPos.x = nLineLength;
+                    }
+                  else
+                               if( ptCurrentPos.x >= nLineLength )
+                                       ptCurrentPos.x = nLineLength - 1;
+                               /*ORIGINAL
+                  if (ptCurrentPos.x == -1)
+                    {
+                      nLineLength = GetLineLength (ptCurrentPos.y);
+                      ptCurrentPos.x = nLineLength;
+                    }
+                  else
+                    nLineLength = ptCurrentPos.x;
+                  if (nLineLength <= 0)
+                    {
+                      ptCurrentPos.x = -1;
+                      ptCurrentPos.y--;
+                      continue;
+                    }
+                               *///END SW
+
+                  LPCTSTR pszChars = GetLineChars (ptCurrentPos.y);
+                               //BEGIN SW
+                               _tcsncpy(line.GetBuffer(ptCurrentPos.x + 2), pszChars, ptCurrentPos.x + 1);
+                               /*ORIGINAL
+                  LPTSTR pszBuf = line.GetBuffer (nLineLength + 1);
+                  _tcsncpy (pszBuf, pszChars, nLineLength);
+                  pszBuf[nLineLength] = _T ('\0');
+                               *///END SW
+                  line.ReleaseBuffer ();
+                  if ((dwFlags & FIND_MATCH_CASE) == 0)
+                    line.MakeUpper ();
+                }
+
+                               //BEGIN SW
+                               int     nFoundPos = -1;
+                               int     nMatchLen = what.GetLength();
+                               int     nLineLen = line.GetLength();
+                               int     nPos;
+                               do
+                               {
+                                       nPos = ::FindStringHelper(line, what, dwFlags, m_nLastFindWhatLen, m_rxnode, &m_rxmatch);
+                                       if( nPos >= 0 )
+                                       {
+                                               nFoundPos = (nFoundPos == -1)? nPos : nFoundPos + nPos;
+                                               nFoundPos+= nMatchLen;
+                                               line = line.Right( nLineLen - (nMatchLen + nPos) );
+                                               nLineLen = line.GetLength();
+                                       }
+                               }
+                               while( nPos >= 0 );
+
+                               if( nFoundPos >= 0 )    // Found text!
+                               {
+                                       ptCurrentPos.x = nFoundPos - nMatchLen;
+                                       *pptFoundPos = ptCurrentPos;
+                                       return TRUE;
+                               }
+
+                               ptCurrentPos.y--;
+                               if( ptCurrentPos.y >= 0 )
+                                       ptCurrentPos.x = GetLineLength( ptCurrentPos.y );
+                               /*ORIGINAL
+              int nPos =::FindStringHelper (line, what, dwFlags, m_nLastFindWhatLen, m_rxnode, &m_rxmatch);
+              if (nPos >= 0)    //  Found text!
+                {
+                  LPTSTR pszText = line.GetBuffer (nLineLength + 1);
+                  m_pszMatched = _tcsdup (pszText);
+                  line.ReleaseBuffer ();
+                  // m_sMatched = line.Mid (nPos);
+                  if (nEolns)
+                    {
+                      CString item = line.Left (nPos);
+                      ptCurrentPos.y -= nEolns - HowManyStr (item, _T('\n'));
+                      if (ptCurrentPos.y < 0)
+                        ptCurrentPos.y = 0;
+                      LPCTSTR current = _tcsrchr (item, _T('\n'));
+                      if (current)
+                        current++;
+                      else
+                        current = item;
+                      ptCurrentPos.x = nPos - (current - (LPCTSTR) item);
+                      if (ptCurrentPos.x < 0)
+                        ptCurrentPos.x = 0;
+                    }
+                  else
+                    {
+                      ptCurrentPos.x = nPos;
+                    }
+                  *pptFoundPos = ptCurrentPos;
+                  return TRUE;
+                }
+              else
+                m_pszMatched = NULL;
+
+              ptCurrentPos.x = -1;
+              ptCurrentPos.y--;
+                               *///END SW
+            }
+
+          //  Beginning of text reached
+          if (!bWrapSearch)
+            return FALSE;
+
+          //  Start again from the end of text
+          bWrapSearch = FALSE;
+          ptCurrentPos = CPoint (0, GetLineCount () - 1);
+        }
+    }
+  else
+    {
+      for (;;)
+        {
+          while (ptCurrentPos.y <= ptBlockEnd.y)
+            {
+              int nLineLength, nLines;
+              CString line;
+              if (dwFlags & FIND_REGEXP)
+                {
+                  nLines = m_pTextBuffer->GetLineCount ();
+                  for (int i = 0; i <= nEolns && ptCurrentPos.y + i < nLines; i++)
+                    {
+                      CString item;
+                      LPCTSTR pszChars = GetLineChars (ptCurrentPos.y + i);
+                      nLineLength = GetLineLength (ptCurrentPos.y + i);
+                      if (i)
+                        {
+                          line += _T ('\n');
+                        }
+                      else
+                        {
+                          pszChars += ptCurrentPos.x;
+                          nLineLength -= ptCurrentPos.x;
+                        }
+                      if (nLineLength > 0)
+                        {
+                          LPTSTR pszBuf = item.GetBuffer (nLineLength + 1);
+                          _tcsncpy (pszBuf, pszChars, nLineLength);
+                          pszBuf[nLineLength] = _T ('\0');
+                          item.ReleaseBuffer ();
+                          line += item;
+                        }
+                    }
+                  nLineLength = line.GetLength ();
+                }
+              else
+                {
+                  nLineLength = GetLineLength (ptCurrentPos.y) - ptCurrentPos.x;
+                  if (nLineLength <= 0)
+                    {
+                      ptCurrentPos.x = 0;
+                      ptCurrentPos.y++;
+                      continue;
+                    }
+
+                  LPCTSTR pszChars = GetLineChars (ptCurrentPos.y);
+                  pszChars += ptCurrentPos.x;
+
+                  //  Prepare necessary part of line
+                  LPTSTR pszBuf = line.GetBuffer (nLineLength + 1);
+                  _tcsncpy (pszBuf, pszChars, nLineLength);
+                  pszBuf[nLineLength] = _T ('\0');
+                  line.ReleaseBuffer ();
+                  if ((dwFlags & FIND_MATCH_CASE) == 0)
+                    line.MakeUpper ();
+                }
+
+              //  Perform search in the line
+              int nPos =::FindStringHelper (line, what, dwFlags, m_nLastFindWhatLen, m_rxnode, &m_rxmatch);
+              if (nPos >= 0)
+                {
+                  LPTSTR pszText = line.GetBuffer (nLineLength + 1);
+                  m_pszMatched = _tcsdup (pszText);
+                  line.ReleaseBuffer ();
+                  // m_sMatched = line.Mid (nPos);
+                  if (nEolns)
+                    {
+                      CString item = line.Left (nPos);
+                      LPCTSTR current = _tcsrchr (item, _T('\n'));
+                      if (current)
+                        current++;
+                      else
+                        current = item;
+                      nEolns = HowManyStr (item, _T('\n'));
+                      if (nEolns)
+                        {
+                          ptCurrentPos.y += nEolns;
+                          ptCurrentPos.x = nPos - (current - (LPCTSTR) item);
+                        }
+                      else
+                        {
+                          ptCurrentPos.x += nPos - (current - (LPCTSTR) item);
+                        }
+                      if (ptCurrentPos.x < 0)
+                        ptCurrentPos.x = 0;
+                    }
+                  else
+                    {
+                      ptCurrentPos.x += nPos;
+                    }
+                  //  Check of the text found is outside the block.
+                  if (ptCurrentPos.y == ptBlockEnd.y && ptCurrentPos.x >= ptBlockEnd.x)
+                    break;
+
+                  *pptFoundPos = ptCurrentPos;
+                  return TRUE;
+                }
+              else
+                m_pszMatched = NULL;
+
+              //  Go further, text was not found
+              ptCurrentPos.x = 0;
+              ptCurrentPos.y++;
+            }
+
+          //  End of text reached
+          if (!bWrapSearch)
+            return FALSE;
+
+          //  Start from the beginning
+          bWrapSearch = FALSE;
+          ptCurrentPos = ptBlockBegin;
+        }
+    }
+
+  ASSERT (FALSE);               // Unreachable
+
+  return FALSE;
+}
+
+void CCrystalTextView::
+OnEditFind ()
+{
+  CWinApp *pApp = AfxGetApp ();
+  ASSERT (pApp != NULL);
+
+  CFindTextDlg dlg (this);
+  if (m_bLastSearch)
+    {
+      //  Get the latest search parameters
+      dlg.m_bMatchCase = (m_dwLastSearchFlags & FIND_MATCH_CASE) != 0;
+      dlg.m_bWholeWord = (m_dwLastSearchFlags & FIND_WHOLE_WORD) != 0;
+      dlg.m_bRegExp = (m_dwLastSearchFlags & FIND_REGEXP) != 0;
+      dlg.m_nDirection = (m_dwLastSearchFlags & FIND_DIRECTION_UP) != 0 ? 0 : 1;
+      if (m_pszLastFindWhat != NULL)
+        dlg.m_sText = m_pszLastFindWhat;
+    }
+  else
+    {
+      DWORD dwFlags;
+      if (!RegLoadNumber (HKEY_CURRENT_USER, REG_EDITPAD, _T ("FindFlags"), &dwFlags))
+        dwFlags = 0;
+      dlg.m_bMatchCase = (dwFlags & FIND_MATCH_CASE) != 0;
+      dlg.m_bWholeWord = (dwFlags & FIND_WHOLE_WORD) != 0;
+      dlg.m_bRegExp = (dwFlags & FIND_REGEXP) != 0;
+      dlg.m_nDirection = (dwFlags & FIND_DIRECTION_UP) == 0;
+      // dlg.m_sText = pApp->GetProfileString (REG_FIND_SUBKEY, REG_FIND_WHAT, _T (""));
+    }
+
+  //  Take the current selection, if any
+  if (IsSelection ())
+    {
+      CPoint ptSelStart, ptSelEnd;
+      GetSelection (ptSelStart, ptSelEnd);
+      if (ptSelStart.y == ptSelEnd.y)
+        {
+          LPCTSTR pszChars = GetLineChars (ptSelStart.y);
+          int nChars = ptSelEnd.x - ptSelStart.x;
+          _tcsncpy (dlg.m_sText.GetBuffer (nChars + 1), pszChars + ptSelStart.x, nChars + 1);
+          dlg.m_sText.ReleaseBuffer ();
+        }
+    }
+  else
+    {
+      CPoint ptCursorPos = GetCursorPos (), ptStart = WordToLeft (ptCursorPos), ptEnd = WordToRight (ptCursorPos);
+      if (IsValidTextPos (ptStart) && IsValidTextPos (ptEnd) && ptStart != ptEnd)
+        GetText (ptStart, ptEnd, dlg.m_sText);
+    }
+
+  //  Execute Find dialog
+  dlg.m_ptCurrentPos = m_ptCursorPos;   //  Search from cursor position
+
+  // m_bShowInactiveSelection = TRUE; // FP: removed because I like it
+  dlg.DoModal ();
+  // m_bShowInactiveSelection = FALSE; // FP: removed because I like it
+
+  //  Save search parameters for 'F3' command
+  m_bLastSearch = TRUE;
+  if (m_pszLastFindWhat != NULL)
+    free (m_pszLastFindWhat);
+  m_pszLastFindWhat = _tcsdup (dlg.m_sText);
+  m_dwLastSearchFlags = 0;
+  if (dlg.m_bMatchCase)
+    m_dwLastSearchFlags |= FIND_MATCH_CASE;
+  if (dlg.m_bWholeWord)
+    m_dwLastSearchFlags |= FIND_WHOLE_WORD;
+  if (dlg.m_bRegExp)
+    m_dwLastSearchFlags |= FIND_REGEXP;
+  if (dlg.m_nDirection == 0)
+    m_dwLastSearchFlags |= FIND_DIRECTION_UP;
+
+  //  Save search parameters to registry
+  VERIFY (RegSaveNumber (HKEY_CURRENT_USER, REG_EDITPAD, _T ("FindFlags"), m_dwLastSearchFlags));
+  // pApp->WriteProfileString (REG_FIND_SUBKEY, REG_FIND_WHAT, dlg.m_sText);
+}
+
+void CCrystalTextView::
+OnEditRepeat ()
+{
+  BOOL bEnable = m_bLastSearch;
+  CString sText;
+  if (bEnable)
+    sText = m_pszLastFindWhat;
+  else
+    {
+      bEnable = CMemComboBox::groups.Lookup (_T ("FindText"), sText) && !sText.IsEmpty ();
+      if (bEnable)
+        {
+          int pos = sText.Find (_T('\n'));
+          if (pos >= 0)
+            sText = sText.Left (pos);
+        }
+    }
+  if (bEnable)
+    {
+      CPoint ptFoundPos;
+               //BEGIN SW
+               // for correct backward search we need some changes:
+               CPoint ptSearchPos = m_ptCursorPos;
+               if( m_dwLastSearchFlags & FIND_DIRECTION_UP && IsSelection() )
+               {
+                       CPoint  ptDummy;
+                       GetSelection( ptSearchPos, ptDummy );
+               }
+
+               if (! FindText(sText, ptSearchPos, m_dwLastSearchFlags, TRUE, &ptFoundPos))
+               /*ORIGINAL
+               if (! FindText(sText, m_ptCursorPos, m_dwLastSearchFlags, TRUE, &ptFoundPos))
+               *///END SW
+        {
+          CString prompt;
+          prompt.Format (IDS_EDIT_TEXT_NOT_FOUND, sText);
+          AfxMessageBox (prompt);
+          return;
+        }
+      HighlightText (ptFoundPos, m_nLastFindWhatLen, (m_dwLastSearchFlags & FIND_DIRECTION_UP) != 0);
+      m_bMultipleSearch = TRUE; // More search
+
+    }
+}
+
+void CCrystalTextView::
+OnUpdateEditRepeat (CCmdUI * pCmdUI)
+{
+  BOOL bEnable = m_bLastSearch;
+  if (!bEnable)
+    {
+      CString sText;
+      bEnable = CMemComboBox::groups.Lookup (_T ("FindText"), sText) && !sText.IsEmpty ();
+    }
+  pCmdUI->Enable (bEnable);
+}
+
+void CCrystalTextView::
+OnEditFindPrevious ()
+{
+  DWORD dwSaveSearchFlags = m_dwLastSearchFlags;
+  if ((m_dwLastSearchFlags & FIND_DIRECTION_UP) != 0)
+    m_dwLastSearchFlags &= ~FIND_DIRECTION_UP;
+  else
+    m_dwLastSearchFlags |= FIND_DIRECTION_UP;
+  OnEditRepeat ();
+  m_dwLastSearchFlags = dwSaveSearchFlags;
+}
+
+void CCrystalTextView::
+OnUpdateEditFindPrevious (CCmdUI * pCmdUI)
+{
+  BOOL bEnable = m_bLastSearch;
+  if (!bEnable)
+    {
+      CString sText;
+      bEnable = CMemComboBox::groups.Lookup (_T ("FindText"), sText) && !sText.IsEmpty ();
+    }
+  pCmdUI->Enable (bEnable);
+}
+
+void CCrystalTextView::
+OnFilePageSetup ()
+{
+  CWinApp *pApp = AfxGetApp ();
+  ASSERT (pApp != NULL);
+
+  CPageSetupDialog dlg;
+  //dlg.m_psd.Flags &= ~PSD_INTHOUSANDTHSOFINCHES;
+  dlg.m_psd.Flags = PSD_INHUNDREDTHSOFMILLIMETERS|PSD_MARGINS;
+  dlg.m_psd.rtMargin.left = DEFAULT_PRINT_MARGIN;
+  dlg.m_psd.rtMargin.right = DEFAULT_PRINT_MARGIN;
+  dlg.m_psd.rtMargin.top = DEFAULT_PRINT_MARGIN;
+  dlg.m_psd.rtMargin.bottom = DEFAULT_PRINT_MARGIN;
+  CReg reg;
+  if (reg.Open (HKEY_CURRENT_USER, REG_EDITPAD, KEY_READ))
+    {
+      DWORD dwTemp;
+      if (reg.LoadNumber (_T ("PageWidth"), &dwTemp))
+        dlg.m_psd.ptPaperSize.x = dwTemp;
+      if (reg.LoadNumber (_T ("PageHeight"), &dwTemp))
+        dlg.m_psd.ptPaperSize.y = dwTemp;
+      if (reg.LoadNumber (_T ("PageLeft"), &dwTemp))
+        dlg.m_psd.rtMargin.left = dwTemp;
+      if (reg.LoadNumber (_T ("PageRight"), &dwTemp))
+        dlg.m_psd.rtMargin.right = dwTemp;
+      if (reg.LoadNumber (_T ("PageTop"), &dwTemp))
+        dlg.m_psd.rtMargin.top = dwTemp;
+      if (reg.LoadNumber (_T ("PageBottom"), &dwTemp))
+        dlg.m_psd.rtMargin.bottom = dwTemp;
+    }
+  if (dlg.DoModal () == IDOK)
+    {
+      CReg reg;
+      if (reg.Create (HKEY_CURRENT_USER, REG_EDITPAD, KEY_WRITE))
+        {
+          VERIFY (reg.SaveNumber (_T ("PageWidth"), dlg.m_psd.ptPaperSize.x));
+          VERIFY (reg.SaveNumber (_T ("PageHeight"), dlg.m_psd.ptPaperSize.y));
+          VERIFY (reg.SaveNumber (_T ("PageLeft"), dlg.m_psd.rtMargin.left));
+          VERIFY (reg.SaveNumber (_T ("PageRight"), dlg.m_psd.rtMargin.right));
+          VERIFY (reg.SaveNumber (_T ("PageTop"), dlg.m_psd.rtMargin.top));
+          VERIFY (reg.SaveNumber (_T ("PageBottom"), dlg.m_psd.rtMargin.bottom));
+        }
+    }
+}
+
+void CCrystalTextView::
+OnToggleBookmark ()
+{
+  if (m_pTextBuffer != NULL)
+    {
+      DWORD dwFlags = GetLineFlags (m_ptCursorPos.y);
+      DWORD dwMask = LF_BOOKMARKS;
+      m_pTextBuffer->SetLineFlag (m_ptCursorPos.y, dwMask, (dwFlags & dwMask) == 0, FALSE);
+    }
+  int nLine = m_pTextBuffer->GetLineWithFlag (LF_BOOKMARKS);
+  if (nLine >= 0)
+    m_bBookmarkExist = TRUE;
+  else
+    m_bBookmarkExist = FALSE;
+}
+
+void CCrystalTextView::
+OnNextBookmark ()
+{
+  if (m_pTextBuffer != NULL)
+    {
+      int nLine = m_pTextBuffer->FindNextBookmarkLine (m_ptCursorPos.y);
+      if (nLine >= 0)
+        {
+          CPoint pt (0, nLine);
+          ASSERT_VALIDTEXTPOS (pt);
+          SetCursorPos (pt);
+          SetSelection (pt, pt);
+          SetAnchor (pt);
+          EnsureVisible (pt);
+        }
+    }
+}
+
+void CCrystalTextView::
+OnPrevBookmark ()
+{
+  if (m_pTextBuffer != NULL)
+    {
+      int nLine = m_pTextBuffer->FindPrevBookmarkLine (m_ptCursorPos.y);
+      if (nLine >= 0)
+        {
+          CPoint pt (0, nLine);
+          ASSERT_VALIDTEXTPOS (pt);
+          SetCursorPos (pt);
+          SetSelection (pt, pt);
+          SetAnchor (pt);
+          EnsureVisible (pt);
+        }
+    }
+}
+
+void CCrystalTextView::
+OnClearAllBookmarks ()
+{
+  if (m_pTextBuffer != NULL)
+    {
+      int nLineCount = GetLineCount ();
+      for (int I = 0; I < nLineCount; I++)
+        {
+          if (m_pTextBuffer->GetLineFlags (I) & LF_BOOKMARKS)
+            m_pTextBuffer->SetLineFlag (I, LF_BOOKMARKS, FALSE);
+        }
+      m_bBookmarkExist = FALSE;
+    }
+}
+
+void CCrystalTextView::
+OnUpdateNextBookmark (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (m_bBookmarkExist);
+}
+
+void CCrystalTextView::
+OnUpdatePrevBookmark (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (m_bBookmarkExist);
+}
+
+void CCrystalTextView::
+OnUpdateClearAllBookmarks (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (m_bBookmarkExist);
+}
+
+BOOL CCrystalTextView::
+GetViewTabs ()
+{
+  return m_bViewTabs;
+}
+
+void CCrystalTextView::
+SetViewTabs (BOOL bViewTabs)
+{
+  if (bViewTabs != m_bViewTabs)
+    {
+      m_bViewTabs = bViewTabs;
+      if (::IsWindow (m_hWnd))
+        Invalidate ();
+    }
+}
+
+DWORD CCrystalTextView::
+GetFlags ()
+{
+  return m_dwFlags;
+}
+
+void CCrystalTextView::
+SetFlags (DWORD dwFlags)
+{
+  if (m_dwFlags != dwFlags)
+    {
+      m_dwFlags = dwFlags;
+      if (::IsWindow (m_hWnd))
+        Invalidate ();
+    }
+}
+
+BOOL CCrystalTextView::
+GetSelectionMargin ()
+{
+  return m_bSelMargin;
+}
+
+int CCrystalTextView::
+GetMarginWidth ()
+{
+  return m_bSelMargin ? 20 : 1;
+}
+
+BOOL CCrystalTextView::
+GetSmoothScroll ()
+const
+{
+  return m_bSmoothScroll;
+}
+
+void CCrystalTextView::SetSmoothScroll (BOOL bSmoothScroll)
+{
+  m_bSmoothScroll = bSmoothScroll;
+}
+
+//  [JRT]
+BOOL CCrystalTextView::
+GetDisableDragAndDrop ()
+const
+{
+  return m_bDisableDragAndDrop;
+}
+
+//  [JRT]
+void CCrystalTextView::SetDisableDragAndDrop (BOOL bDDAD)
+{
+  m_bDisableDragAndDrop = bDDAD;
+}
+
+//
+// Mouse wheel event.  zDelta is in multiples of 120.
+// Divide by 40 so each click is 3 lines.  I know some
+// drivers let you set the ammount of scroll, but I
+// don't know how to retrieve this or if they just
+// adjust the zDelta you get here.
+BOOL CCrystalTextView::
+OnMouseWheel (UINT nFlags, short zDelta, CPoint pt)
+{
+       // -> HE
+       int nPageLines = GetScreenLines();
+       int nSubLineCount = GetSubLineCount();
+
+       int nNewTopSubLine= m_nTopSubLine - zDelta / 40;
+
+       if (nNewTopSubLine < 0)
+               nNewTopSubLine = 0;
+       if (nNewTopSubLine >= nSubLineCount)
+               nNewTopSubLine = nSubLineCount - 1;
+
+       ScrollToSubLine(nNewTopSubLine, TRUE);
+       UpdateSiblingScrollPos(FALSE);
+       // <- HE
+/* Old
+  int nLineCount = GetLineCount ();
+
+  int nNewTopLine = m_nTopLine - zDelta / 40;
+
+  if (nNewTopLine < 0)
+    nNewTopLine = 0;
+  if (nNewTopLine >= nLineCount)
+    nNewTopLine = nLineCount - 1;
+
+  if (m_nTopLine != nNewTopLine)
+    {
+      int nScrollLines = m_nTopLine - nNewTopLine;
+      m_nTopLine = nNewTopLine;
+      ScrollWindow (0, nScrollLines * GetLineHeight ());
+      UpdateWindow ();
+    }
+
+  RecalcVertScrollBar (TRUE);
+*/
+
+  return CView::OnMouseWheel (nFlags, zDelta, pt);
+}
+
+void CCrystalTextView::
+OnSourceType (UINT nId)
+{
+  SetTextType ((CCrystalTextView::TextType) (nId - ID_SOURCE_PLAIN));
+  Invalidate ();
+}
+
+void CCrystalTextView::
+OnUpdateSourceType (CCmdUI * pCmdUI)
+{
+  pCmdUI->SetRadio (m_SourceDefs + (pCmdUI->m_nID - ID_SOURCE_PLAIN) == m_CurSourceDef);
+}
+
+int bracetype (TCHAR c);
+
+void CCrystalTextView::
+OnMatchBrace ()
+{
+  CPoint ptCursorPos = GetCursorPos ();
+  int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
+  LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y), pszEnd = pszText + ptCursorPos.x;
+  bool bAfter;
+  int nType = 0;
+  if (ptCursorPos.x < nLength)
+    {
+      nType = bracetype (*pszEnd);
+      if (nType)
+        {
+          bAfter = false;
+        }
+      else if (!nType && ptCursorPos.x > 0)
+        {
+          nType = bracetype (pszEnd[-1]);
+          bAfter = true;
+        }
+    }
+  else if (ptCursorPos.x > 0)
+    {
+      nType = bracetype (pszEnd[-1]);
+      bAfter = true;
+    }
+  if (nType)
+    {
+      int nOther, nCount = 0, nComment = 0;
+      if (bAfter)
+        {
+          nOther = ((nType - 1) ^ 1) + 1;
+          if (nOther & 1)
+            pszEnd--;
+        }
+      else
+        {
+          nOther = ((nType - 1) ^ 1) + 1;
+          if (!(nOther & 1))
+            pszEnd++;
+        }
+      LPCTSTR pszOpenComment = m_CurSourceDef->opencomment,
+        pszCloseComment = m_CurSourceDef->closecomment,
+        pszCommentLine = m_CurSourceDef->commentline, pszTest;
+      int nOpenComment = _tcslen (pszOpenComment),
+        nCloseComment = _tcslen (pszCloseComment),
+        nCommentLine = _tcslen (pszCommentLine);
+      if (nOther & 1)
+        {
+          for (;;)
+            {
+              while (--pszEnd >= pszText)
+                {
+                  pszTest = pszEnd - nOpenComment + 1;
+                  if (pszTest >= pszText && !_tcsnicmp (pszTest, pszOpenComment, nOpenComment))
+                    {
+                      nComment--;
+                      pszEnd = pszTest;
+                      if (--pszEnd < pszText)
+                        {
+                          break;
+                        }
+                    }
+                  pszTest = pszEnd - nCloseComment + 1;
+                  if (pszTest >= pszText && !_tcsnicmp (pszTest, pszCloseComment, nCloseComment))
+                    {
+                      nComment++;
+                      pszEnd = pszTest;
+                      if (--pszEnd < pszText)
+                        {
+                          break;
+                        }
+                    }
+                  if (!nComment)
+                    {
+                      pszTest = pszEnd - nCommentLine + 1;
+                      if (pszTest >= pszText && !_tcsnicmp (pszTest, pszCommentLine, nCommentLine))
+                        {
+                          break;
+                        }
+                      if (bracetype (*pszEnd) == nType)
+                        {
+                          nCount++;
+                        }
+                      else if (bracetype (*pszEnd) == nOther)
+                        {
+                          if (!nCount--)
+                            {
+                              ptCursorPos.x = pszEnd - pszText;
+                              if (bAfter)
+                                ptCursorPos.x++;
+                              SetCursorPos (ptCursorPos);
+                              SetSelection (ptCursorPos, ptCursorPos);
+                              SetAnchor (ptCursorPos);
+                              EnsureVisible (ptCursorPos);
+                              return;
+                            }
+                        }
+                    }
+                }
+              if (ptCursorPos.y)
+                {
+                  ptCursorPos.x = m_pTextBuffer->GetLineLength (--ptCursorPos.y);
+                  pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y);
+                  pszEnd = pszText + ptCursorPos.x;
+                }
+              else
+                break;
+            }
+        }
+      else
+        {
+          LPCTSTR pszBegin = pszText;
+          pszText = pszEnd;
+          pszEnd = pszBegin + nLength;
+          int nLines = m_pTextBuffer->GetLineCount ();
+          for (;;)
+            {
+              while (pszText < pszEnd)
+                {
+                  pszTest = pszText + nCloseComment;
+                  if (pszTest <= pszEnd && !_tcsnicmp (pszText, pszCloseComment, nCloseComment))
+                    {
+                      nComment--;
+                      pszText = pszTest;
+                      if (pszText > pszEnd)
+                        {
+                          break;
+                        }
+                    }
+                  pszTest = pszText + nOpenComment;
+                  if (pszTest <= pszEnd && !_tcsnicmp (pszText, pszOpenComment, nOpenComment))
+                    {
+                      nComment++;
+                      pszText = pszTest;
+                      if (pszText > pszEnd)
+                        {
+                          break;
+                        }
+                    }
+                  if (!nComment)
+                    {
+                      pszTest = pszText + nCommentLine;
+                      if (pszTest <= pszEnd && !_tcsnicmp (pszText, pszCommentLine, nCommentLine))
+                        {
+                          break;
+                        }
+                      if (bracetype (*pszText) == nType)
+                        {
+                          nCount++;
+                        }
+                      else if (bracetype (*pszText) == nOther)
+                        {
+                          if (!nCount--)
+                            {
+                              ptCursorPos.x = pszText - pszBegin;
+                              if (bAfter)
+                                ptCursorPos.x++;
+                              SetCursorPos (ptCursorPos);
+                              SetSelection (ptCursorPos, ptCursorPos);
+                              SetAnchor (ptCursorPos);
+                              EnsureVisible (ptCursorPos);
+                              return;
+                            }
+                        }
+                    }
+                  pszText++;
+                }
+              if (ptCursorPos.y < nLines)
+                {
+                  ptCursorPos.x = 0;
+                  nLength = m_pTextBuffer->GetLineLength (++ptCursorPos.y);
+                  pszBegin = pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y);
+                  pszEnd = pszBegin + nLength;
+                }
+              else
+                break;
+            }
+        }
+    }
+}
+
+void CCrystalTextView::
+OnUpdateMatchBrace (CCmdUI * pCmdUI)
+{
+  CPoint ptCursorPos = GetCursorPos ();
+  int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
+  LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y) + ptCursorPos.x;
+  pCmdUI->Enable (ptCursorPos.x < nLength && (bracetype (*pszText) || ptCursorPos.x > 0 && bracetype (pszText[-1])) || ptCursorPos.x > 0 && bracetype (pszText[-1]));
+}
+
+void CCrystalTextView::
+OnEditGoTo ()
+{
+  CGotoDlg dlg (this);
+  dlg.DoModal ();
+}
+
+void CCrystalTextView::
+OnUpdateToggleSourceHeader (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (m_CurSourceDef->type == SRC_C);
+}
+
+void CCrystalTextView::
+OnToggleSourceHeader ()
+{
+  if (m_CurSourceDef->type == SRC_C)
+    {
+      CDocument *pDoc = GetDocument ();
+      ASSERT (pDoc);
+      CString sFilePath = pDoc->GetPathName (), sOriginalPath = sFilePath;
+      if (!_tcsicmp (sFilePath.Right (2), _T (".c")))
+        {
+          sFilePath = sFilePath.Left (sFilePath.GetLength () - 1) + _T ('h');
+        }
+      else if (!_tcsicmp (sFilePath.Right (4), _T (".cpp")))
+        {
+          sFilePath = sFilePath.Left (sFilePath.GetLength () - 3) + _T ('h');
+        }
+      else if (!_tcsicmp (sFilePath.Right (4), _T (".inl")))
+        {
+          sFilePath = sFilePath.Left (sFilePath.GetLength () - 3) + _T ('c');
+          if (!FileExist(sFilePath))
+            {
+              sFilePath = sFilePath + _T ("pp");
+            }
+        }
+      else if (!_tcsicmp (sFilePath.Right (4), _T (".hpp")))
+        {
+          sFilePath = sFilePath.Left (sFilePath.GetLength () - 3) + _T ("inl");
+          if (!FileExist(sFilePath))
+            {
+              sFilePath = sFilePath.Left (sFilePath.GetLength () - 3) + _T ('c');
+              if (!FileExist(sFilePath))
+                {
+                  sFilePath = sFilePath + _T ("pp");
+                }
+            }
+        }
+      else if (!_tcsicmp (sFilePath.Right (2), _T (".h")))
+        {
+          sFilePath = sFilePath.Left (sFilePath.GetLength () - 1) + _T ("hpp");
+          if (!FileExist(sFilePath))
+            {
+              sFilePath = sFilePath.Left (sFilePath.GetLength () - 3) + _T ("inl");
+              if (!FileExist(sFilePath))
+                {
+                  sFilePath = sFilePath.Left (sFilePath.GetLength () - 3) + _T ('c');
+                  if (!FileExist(sFilePath))
+                    {
+                      sFilePath = sFilePath + _T ("pp");
+                    }
+                }
+            }
+        }
+      if (FileExist(sFilePath))
+        {
+          if (!m_bSingle || !pDoc->IsModified () || pDoc->DoSave (sOriginalPath))
+            {
+              AfxGetApp ()->OpenDocumentFile (sFilePath);
+              if (m_bSingle)
+                {
+                  m_ptCursorLast.x = m_ptCursorLast.y = 0;
+                  ASSERT_VALIDTEXTPOS (m_ptCursorLast);
+                  CPoint ptCursorPos = m_ptCursorLast;
+                  SetCursorPos (ptCursorPos);
+                  SetSelection (ptCursorPos, ptCursorPos);
+                  SetAnchor (ptCursorPos);
+                  EnsureVisible (ptCursorPos);
+                  Invalidate ();
+                }
+            }
+        }
+    }
+}
+
+void CCrystalTextView::
+OnUpdateSelMargin (CCmdUI * pCmdUI)
+{
+  pCmdUI->SetCheck (m_bSelMargin);
+}
+
+void CCrystalTextView::
+OnSelMargin ()
+{
+  ASSERT (m_CurSourceDef);
+  if (m_bSelMargin)
+    {
+      m_CurSourceDef->flags &= ~SRCOPT_SELMARGIN;
+      SetSelectionMargin (FALSE);
+    }
+  else
+    {
+      m_CurSourceDef->flags |= SRCOPT_SELMARGIN;
+      SetSelectionMargin (TRUE);
+    }
+}
+
+void CCrystalTextView::
+OnUpdateWordWrap (CCmdUI * pCmdUI)
+{
+  pCmdUI->SetCheck (m_bWordWrap);
+}
+
+void CCrystalTextView::
+OnWordWrap ()
+{
+  ASSERT (m_CurSourceDef);
+  if (m_bWordWrap)
+    {
+      m_CurSourceDef->flags &= ~SRCOPT_WORDWRAP;
+      SetWordWrapping (FALSE);
+    }
+  else
+    {
+      m_CurSourceDef->flags |= SRCOPT_WORDWRAP;
+      SetWordWrapping (TRUE);
+    }
+}
+
+void CCrystalTextView::
+OnForceRedraw ()
+{
+  //Invalidate ();
+  RedrawWindow (NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW);
+}
+
+//BEGIN SW
+BOOL CCrystalTextView::GetWordWrapping() const
+{
+       return m_bWordWrap;
+}
+
+void CCrystalTextView::SetWordWrapping( BOOL bWordWrap )
+{
+       m_bWordWrap = bWordWrap;
+
+       if( IsWindow( m_hWnd ) )
+               InvalidateLines( 0, -1, TRUE );
+}
+
+CCrystalParser *CCrystalTextView::SetParser( CCrystalParser *pParser )
+{
+       CCrystalParser  *pOldParser = m_pParser;
+
+       m_pParser = pParser;
+
+       if( pParser )
+               pParser->m_pTextView = this;
+
+       return pOldParser;
+}
+//END SW
+
+
+//BEGIN SW
+// incremental search imlementation
+BOOL CCrystalTextView::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO *pHandlerInfo )
+{
+       // just look for commands
+       if( nCode != CN_COMMAND || pExtra )
+               return CView::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
+
+       // handle code:
+       // each command that is not related to incremental search
+       // ends the incremental search
+       if( nID == ID_EDIT_FIND_INCREMENTAL_FORWARD || 
+               nID == ID_EDIT_FIND_INCREMENTAL_BACKWARD || 
+               nID == ID_EDIT_DELETE_BACK )
+               return CView::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
+
+       if( nID >= ID_EDIT_FIRST && nID <= ID_EDIT_LAST )
+               m_bIncrementalSearchForward = m_bIncrementalSearchBackward = FALSE;
+
+       return CView::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
+}
+
+void CCrystalTextView::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags )
+{
+       CView::OnChar( nChar, nRepCnt, nFlags );
+
+       // we only have to handle character-input, if we are in incremental search mode
+       if( !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
+               return;
+
+       // exit incremental search, wenn Escape is pressed
+       if( nChar == VK_ESCAPE )
+       {
+               // if not end incremental search
+               m_bIncrementalSearchForward = m_bIncrementalSearchBackward = FALSE;
+               SetSelection( m_selStartBeforeIncrementalSearch, m_selEndBeforeIncrementalSearch );
+               SetCursorPos( m_cursorPosBeforeIncrementalSearch );
+               EnsureVisible( m_cursorPosBeforeIncrementalSearch );
+               return;
+       }
+
+  // exit incremental search without destroying selection
+  if( nChar == VK_RETURN )
+  {
+    m_bIncrementalSearchForward = m_bIncrementalSearchBackward = FALSE;
+    return;
+  }
+
+       // is the character valid for incremental search?
+       if( !_istgraph( nChar ) && !(nChar == _T(' ')) && !(nChar == _T('\t')) )
+       {
+               // if not end incremental search
+               m_bIncrementalSearchForward = m_bIncrementalSearchBackward = FALSE;
+               return;
+       }
+
+       // if last search was not successfull do not add a new character
+       if( !m_bIncrementalFound )
+       {
+               MessageBeep( MB_OK );
+               return;
+       }
+
+       // add character to incremental search string and search
+       *m_pstrIncrementalSearchString += (TCHAR) nChar;
+       OnEditFindIncremental();
+}
+
+
+void CCrystalTextView::OnEditDeleteBack() 
+{
+       if( !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
+               return;
+
+       // remove last character from search string
+       if( m_pstrIncrementalSearchString->IsEmpty() )
+               return;
+
+       *m_pstrIncrementalSearchString = m_pstrIncrementalSearchString->Left( m_pstrIncrementalSearchString->GetLength() - 1 );
+       OnEditFindIncremental();
+}
+
+
+void CCrystalTextView::OnEditFindIncremental( BOOL bFindNextOccurence /*= FALSE*/ )
+{
+       // when string is empty, then goto position where the search starts
+       if( m_pstrIncrementalSearchString->IsEmpty() )
+       {
+               SetSelection( m_incrementalSearchStartPos, m_incrementalSearchStartPos );
+               SetCursorPos( m_incrementalSearchStartPos );
+               EnsureVisible( m_incrementalSearchStartPos );
+               return;
+       }
+
+       // otherwise search next occurence of search string, 
+       // starting at current cursor position
+       CPoint  matchStart, matchEnd;
+
+       // calculate start point for search
+       if( bFindNextOccurence )
+       {
+               CPoint  selStart, selEnd;
+               GetSelection( selStart, selEnd );
+               m_incrementalSearchStartPos = (m_bIncrementalSearchBackward)? selStart : selEnd;
+       }
+
+       m_bIncrementalFound = FindText( 
+               *m_pstrIncrementalSearchString,
+               m_incrementalSearchStartPos,
+               m_bIncrementalSearchBackward? FIND_DIRECTION_UP : 0,
+               TRUE,
+               &matchStart );
+
+       if( !m_bIncrementalFound )
+       {
+               MessageBeep( MB_OK );
+               return;
+       }
+
+       // select found text and set cursor to end of match
+       matchEnd = matchStart;
+       matchEnd.x+= m_pstrIncrementalSearchString->GetLength();
+       SetSelection( matchStart, matchEnd );
+       SetCursorPos( matchEnd );
+       EnsureVisible( matchEnd );
+}
+
+
+
+void CCrystalTextView::OnEditFindIncrementalForward()
+{
+       if( !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
+       {
+               // initialize
+               if( !m_pstrIncrementalSearchString->IsEmpty() )
+                       *m_pstrIncrementalSearchStringOld = *m_pstrIncrementalSearchString;
+               m_pstrIncrementalSearchString->Empty();
+               m_incrementalSearchStartPos = m_cursorPosBeforeIncrementalSearch = m_ptCursorPos;
+               GetSelection( m_selStartBeforeIncrementalSearch, m_selEndBeforeIncrementalSearch );
+       }
+       else if( m_bIncrementalSearchForward )
+       {
+               if( m_pstrIncrementalSearchString->IsEmpty() )
+               {
+                       *m_pstrIncrementalSearchString = *m_pstrIncrementalSearchStringOld;
+                       m_pstrIncrementalSearchStringOld->Empty();
+                       OnEditFindIncremental();
+               }
+               else
+                       OnEditFindIncremental( TRUE );
+
+               return;
+       }
+
+       m_bIncrementalSearchForward = TRUE;
+       m_bIncrementalSearchBackward = FALSE;
+       m_bIncrementalFound = TRUE;
+       OnEditFindIncremental();
+}
+
+void CCrystalTextView::OnEditFindIncrementalBackward()
+{
+       if( !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
+       {
+               // initialize
+               if( !m_pstrIncrementalSearchString->IsEmpty() )
+                       *m_pstrIncrementalSearchStringOld = *m_pstrIncrementalSearchString;
+               m_pstrIncrementalSearchString->Empty();
+               GetSelection( m_selStartBeforeIncrementalSearch, m_selEndBeforeIncrementalSearch );
+               m_incrementalSearchStartPos = m_cursorPosBeforeIncrementalSearch = m_ptCursorPos;
+       }
+       else if( m_bIncrementalSearchBackward )
+       {
+               if( m_pstrIncrementalSearchString->IsEmpty() )
+               {
+                       *m_pstrIncrementalSearchString = *m_pstrIncrementalSearchStringOld;
+                       m_pstrIncrementalSearchStringOld->Empty();
+                       OnEditFindIncremental();
+               }
+               else
+                       OnEditFindIncremental( TRUE );
+
+               return;
+       }
+
+       m_bIncrementalSearchForward = FALSE;
+       m_bIncrementalSearchBackward = TRUE;
+       m_bIncrementalFound = TRUE;
+       OnEditFindIncremental();
+}
+
+void CCrystalTextView::OnUpdateEditFindIncrementalForward(CCmdUI* pCmdUI)
+{
+  if (m_pTextBuffer)
+    {
+      int nLines = m_pTextBuffer->GetLineCount ();
+      int nChars = m_pTextBuffer->GetLineLength (m_ptCursorPos.y);
+      pCmdUI->Enable(m_ptCursorPos.y < nLines - 1 || m_ptCursorPos.x < nChars);
+      return;
+    }
+  pCmdUI->Enable(FALSE);
+}
+
+void CCrystalTextView::OnUpdateEditFindIncrementalBackward(CCmdUI* pCmdUI)
+{
+  if (m_pTextBuffer)
+    {
+      pCmdUI->Enable(m_ptCursorPos.y > 0 || m_ptCursorPos.x > 0);
+      return;
+    }
+  pCmdUI->Enable(FALSE);
+}
+
+void CCrystalTextView::OnUpdateStatusMessage( CStatusBar *pStatusBar )
+{
+       static BOOL     bUpdatedAtLastCall = FALSE;
+
+       ASSERT( pStatusBar && IsWindow( pStatusBar->m_hWnd ) );
+       if( !pStatusBar || !IsWindow( pStatusBar->m_hWnd ) )
+               return;
+
+       if( !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
+       {
+               if( bUpdatedAtLastCall )
+                       pStatusBar->SetPaneText( 0, CString( (LPCTSTR)AFX_IDS_IDLEMESSAGE ) );
+
+               bUpdatedAtLastCall = FALSE;
+
+               return;
+       }
+
+       CString strFormat;
+       if( !m_bIncrementalFound )
+               strFormat.Format( IDS_FIND_INCREMENTAL_FAILED, *m_pstrIncrementalSearchString );
+       else if( m_bIncrementalSearchForward )
+               strFormat.Format( IDS_FIND_INCREMENTAL_FORWARD, *m_pstrIncrementalSearchString );
+       else if( m_bIncrementalSearchBackward )
+               strFormat.Format( IDS_FIND_INCREMENTAL_BACKWARD, *m_pstrIncrementalSearchString );
+
+       if( strFormat.IsEmpty() )
+               return;
+
+       pStatusBar->SetPaneText( 0, strFormat );
+       bUpdatedAtLastCall = TRUE;
+}
+//END SW
+
+////////////////////////////////////////////////////////////////////////////
+#pragma warning ( default : 4100 )
diff --git a/Src/editlib/ccrystaltextview.h b/Src/editlib/ccrystaltextview.h
new file mode 100644 (file)
index 0000000..a7ee1c8
--- /dev/null
@@ -0,0 +1,902 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ccrystaltextview.h
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Interface of the CCrystalTextView class, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CCRYSTALTEXTVIEW_H__AD7F2F41_6CB3_11D2_8C32_0080ADB86836__INCLUDED_)
+#define AFX_CCRYSTALTEXTVIEW_H__AD7F2F41_6CB3_11D2_8C32_0080ADB86836__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "cregexp.h"
+#include "crystalparser.h"
+
+////////////////////////////////////////////////////////////////////////////
+// Forward class declarations
+
+class CCrystalTextBuffer;
+class CUpdateContext;
+
+
+////////////////////////////////////////////////////////////////////////////
+// CCrystalTextView class declaration
+
+//  CCrystalTextView::FindText() flags
+enum
+{
+  FIND_MATCH_CASE = 0x0001,
+  FIND_WHOLE_WORD = 0x0002,
+  FIND_REGEXP = 0x0004,
+  FIND_DIRECTION_UP = 0x0010,
+  REPLACE_SELECTION = 0x0100
+};
+
+//  CCrystalTextView::UpdateView() flags
+enum
+{
+  UPDATE_HORZRANGE = 0x0001,  //  update horz scrollbar
+  UPDATE_VERTRANGE = 0x0002, //  update vert scrollbar
+  UPDATE_SINGLELINE = 0x0100,    //  single line has changed
+  UPDATE_FLAGSONLY = 0x0200, //  only line-flags were changed
+
+  UPDATE_RESET = 0x1000       //  document was reloaded, update all!
+};
+
+class EDITPADC_CLASS CCrystalTextView : public CView
+  {
+    DECLARE_DYNCREATE (CCrystalTextView)
+
+       //BEGIN SW
+       friend CCrystalParser;
+       //END SW
+
+protected:
+    //  Search parameters
+    BOOL m_bLastSearch;
+    DWORD m_dwLastSearchFlags;
+    LPTSTR m_pszLastFindWhat;
+    BOOL m_bMultipleSearch;       // More search
+
+private :
+    BOOL m_bCursorHidden;
+
+    //  Painting caching bitmap
+    CBitmap *m_pCacheBitmap;
+
+    //  Line/character dimensions
+    int m_nLineHeight, m_nCharWidth;
+    void CalcLineCharDim ();
+
+    //  Text attributes
+    int m_nTabSize;
+    BOOL m_bViewTabs;
+    BOOL m_bSelMargin;
+    DWORD m_dwFlags;
+
+    //  Amount of lines/characters that completely fits the client area
+    int m_nScreenLines, m_nScreenChars;
+
+    //BEGIN SW
+    /**
+    Contains for each line the number of sublines. If the line is not
+    wrapped, the value for this line is 1. The value of a line is invalid,
+    if it is -1.
+
+    Must create pointer, because contructor uses AFX_ZERO_INIT_OBJECT to
+    initialize the member objects. This would destroy a CArray object.
+    */
+    CArray<int, int> *m_panSubLines;
+    //END SW
+
+    int m_nMaxLineLength;
+    int m_nIdealCharPos;
+
+    BOOL m_bFocused;
+    CPoint m_ptAnchor;
+    LOGFONT m_lfBaseFont;
+    CFont *m_apFonts[4];
+
+    //  Parsing stuff
+    DWORD *m_pdwParseCookies;
+    int m_nParseArraySize;
+    DWORD GetParseCookie (int nLineIndex);
+
+    //  Pre-calculated line lengths (in characters)
+    int m_nActualLengthArraySize;
+    int *m_pnActualLineLength;
+
+    BOOL m_bPreparingToDrag;
+    BOOL m_bDraggingText;
+    BOOL m_bDragSelection, m_bWordSelection, m_bLineSelection;
+    UINT m_nDragSelTimer;
+
+    CPoint m_ptDrawSelStart, m_ptDrawSelEnd;
+    CPoint m_ptCursorPos, m_ptCursorLast;
+    CPoint m_ptSelStart, m_ptSelEnd;
+    void PrepareSelBounds ();
+
+    //  Helper functions
+    void ExpandChars (LPCTSTR pszChars, int nOffset, int nCount, CString & line);
+
+    int ApproxActualOffset (int nLineIndex, int nOffset);
+    void AdjustTextPoint (CPoint & point);
+    void DrawLineHelperImpl (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip,
+                             LPCTSTR pszChars, int nOffset, int nCount);
+    BOOL IsInsideSelBlock (CPoint ptTextPos);
+
+    BOOL m_bBookmarkExist;        // More bookmarks
+
+public :
+    virtual void ResetView ();
+    virtual int GetLineCount ();
+
+protected :
+    CPoint WordToRight (CPoint pt);
+    CPoint WordToLeft (CPoint pt);
+
+    bool m_bSingle;
+    CImageList * m_pIcons;
+    CCrystalTextBuffer *m_pTextBuffer;
+    HACCEL m_hAccel;
+    BOOL m_bVertScrollBarLocked, m_bHorzScrollBarLocked;
+    CPoint m_ptDraggedTextBegin, m_ptDraggedTextEnd;
+    void UpdateCaret ();
+    void SetAnchor (const CPoint & ptNewAnchor);
+    int GetMarginWidth ();
+    bool IsValidTextPos (const CPoint &point);
+    bool IsValidTextPosX (const CPoint &point);
+    bool IsValidTextPosY (const CPoint &point);
+
+    BOOL m_bShowInactiveSelection;
+    //  [JRT]
+    BOOL m_bDisableDragAndDrop;
+
+    //BEGIN SW
+    BOOL m_bWordWrap;
+    CCrystalParser *m_pParser;
+    //END SW
+
+    CPoint ClientToText (const CPoint & point);
+    CPoint TextToClient (const CPoint & point);
+    void InvalidateLines (int nLine1, int nLine2, BOOL bInvalidateMargin = FALSE);
+    int CalculateActualOffset (int nLineIndex, int nCharIndex);
+
+    //  Printing
+    int m_nPrintPages;
+    int *m_pnPages;
+    CFont *m_pPrintFont;
+    int m_nPrintLineHeight;
+    BOOL m_bPrintHeader, m_bPrintFooter;
+    CRect m_ptPageArea, m_rcPrintArea;
+    int PrintLineHeight (CDC * pdc, int nLine);
+    void RecalcPageLayouts (CDC * pdc, CPrintInfo * pInfo);
+    virtual void PrintHeader (CDC * pdc, int nPageNum);
+    virtual void PrintFooter (CDC * pdc, int nPageNum);
+    virtual void GetPrintHeaderText (int nPageNum, CString & text);
+    virtual void GetPrintFooterText (int nPageNum, CString & text);
+
+    //  Keyboard handlers
+    void MoveLeft (BOOL bSelect);
+    void MoveRight (BOOL bSelect);
+    void MoveWordLeft (BOOL bSelect);
+    void MoveWordRight (BOOL bSelect);
+    void MoveUp (BOOL bSelect);
+    void MoveDown (BOOL bSelect);
+    void MoveHome (BOOL bSelect);
+    void MoveEnd (BOOL bSelect);
+    void MovePgUp (BOOL bSelect);
+    void MovePgDn (BOOL bSelect);
+    void MoveCtrlHome (BOOL bSelect);
+    void MoveCtrlEnd (BOOL bSelect);
+
+    void SelectAll ();
+    void Copy ();
+
+    BOOL IsSelection ();
+    BOOL IsInsideSelection (const CPoint & ptTextPos);
+    void GetSelection (CPoint & ptStart, CPoint & ptEnd);
+    void SetSelection (const CPoint & ptStart, const CPoint & ptEnd);
+
+    int m_nTopLine, m_nOffsetChar;
+    //BEGIN SW
+    /**
+    The index of the subline that is the first visible line on the screen.
+    */
+    int m_nTopSubLine;
+    //END SW
+    BOOL m_bSmoothScroll;
+
+    int GetLineHeight ();
+       //BEGIN SW
+       /**
+       Returns the number of sublines the given line contains of.
+       Allway "1", if word wrapping is disabled.
+
+       @param nLineIndex Index of the line to get the subline count of.
+
+       @return Number of sublines the given line contains of
+       */
+       int GetSubLines( int nLineIndex );
+
+       /**
+       Converts the given character position for the given line into a point.
+
+       After the call the x-member of the returned point contains the
+       character position relative to the beginning of the subline. The y-member
+       contains the zero based index of the subline relative to the line, the
+       character position was given for.
+
+       @param nLineIndex Zero based index of the line, nCharPos refers to.
+       @param nCharPos The character position, the point shoult be calculated for.
+       @param charPoint Reference to a point, which should receive the result.
+
+       @return The character position of the beginning of the subline charPoint.y.
+       */
+       int CharPosToPoint( int nLineIndex, int nCharPos, CPoint &charPoint );
+
+       /**
+       Converts the given cursor point for the given line to the character position
+       for the given line.
+
+       The y-member of the cursor position specifies the subline inside the given
+       line, the cursor is placed on and the x-member specifies the cursor position
+       (in character widths) relative to the beginning of that subline.
+
+       @param nLineIndex Zero based index of the line the cursor position refers to.
+       @param curPoint Position of the cursor relative to the line in sub lines and
+               char widths.
+
+       @return The character position the best matches the cursor position.
+       */
+       int CursorPointToCharPos( int nLineIndex, const CPoint &curPoint );
+
+       /**
+       Converts the given cursor position to a text position.
+
+       The x-member of the subLinePos parameter describes the cursor position in
+       char widths relative to the beginning of the subline described by the
+       y-member. The subline is the zero based number of the subline relative to
+       the beginning of the text buffer.
+
+       <p>
+       The returned point contains a valid text position, where the y-member is
+       the zero based index of the textline and the x-member is the character
+       position inside this line.
+
+       @param subLinePos The sublinebased cursor position
+               (see text above for detailed description).
+       @param textPos The calculated line and character position that best matches
+               the cursor position (see text above for detailed descritpion).
+       */
+       void SubLineCursorPosToTextPos( const CPoint &subLinePos, CPoint &textPos );
+
+       /**
+       Returns the character position relative to the given line, that matches
+       the end of the given sub line.
+
+       @param nLineIndex Zero based index of the line to work on.
+       @param nSubLineOffset Zero based index of the subline inside the given line.
+
+       @return Character position that matches the end of the given subline, relative
+               to the given line.
+       */
+       int SubLineEndToCharPos( int nLineIndex, int nSubLineOffset );
+
+       /**
+       Returns the character position relative to the given line, that matches
+       the start of the given sub line.
+
+       @param nLineIndex Zero based index of the line to work on.
+       @param nSubLineOffset Zero based index of the subline inside the given line.
+
+       @return Character position that matches the start of the given subline, relative
+               to the given line.
+       */
+       int SubLineHomeToCharPos( int nLineIndex, int nSubLineOffset );
+       //END SW
+    int GetCharWidth ();
+    int GetMaxLineLength ();
+    int GetScreenLines ();
+    int GetScreenChars ();
+    CFont *GetFont (BOOL bItalic = FALSE, BOOL bBold = FALSE);
+
+    void RecalcVertScrollBar (BOOL bPositionOnly = FALSE);
+    void RecalcHorzScrollBar (BOOL bPositionOnly = FALSE);
+
+    //  Scrolling helpers
+    void ScrollToChar (int nNewOffsetChar, BOOL bNoSmoothScroll = FALSE, BOOL bTrackScrollBar = TRUE);
+    void ScrollToLine (int nNewTopLine, BOOL bNoSmoothScroll = FALSE, BOOL bTrackScrollBar = TRUE);
+
+       //BEGIN SW
+       /**
+       Scrolls to the given sub line, so that the sub line is the first visible
+       line on the screen.
+
+       @param nNewTopSubLine Index of the sub line to scroll to.
+       @param bNoSmoothScroll TRUE to disable smooth scrolling, else FALSE.
+       @param bTrackScrollBar TRUE to recalculate the scroll bar after scrolling,
+               else FALSE.
+       */
+       void ScrollToSubLine( int nNewTopSubLine, BOOL bNoSmoothScroll = FALSE, BOOL bTrackScrollBar = TRUE );
+       //END SW
+
+    //  Splitter support
+    virtual void UpdateSiblingScrollPos (BOOL bHorz);
+    virtual void OnUpdateSibling (CCrystalTextView * pUpdateSource, BOOL bHorz);
+    CCrystalTextView *GetSiblingView (int nRow, int nCol);
+
+       //BEGIN SW
+       /**
+       Returns the number of sublines in the whole text buffer.
+
+       The number of sublines is the sum of all sublines of all lines.
+
+       @return Number of sublines in the whole text buffer.
+       */
+       virtual int GetSubLineCount();
+
+       /**
+       Returns the zero-based subline index of the given line.
+
+       @param nLineIndex Index of the line to calculate the subline index of
+
+       @return The zero-based subline index of the given line.
+       */
+       virtual int GetSubLineIndex( int nLineIndex );
+
+       /**
+       Splits the given subline index into line and sub line of this line.
+
+       @param nSubLineIndex The zero based index of the subline to get info about
+       @param nLine Gets the line number the give subline is included in
+       @param nSubLine Get the subline of the given subline relative to nLine
+       */
+       virtual void GetLineBySubLine( int nSubLineIndex, int &nLine, int &nSubLine );
+       //END SW
+
+    virtual int GetLineLength (int nLineIndex);
+    virtual int GetLineActualLength (int nLineIndex);
+    virtual LPCTSTR GetLineChars (int nLineIndex);
+    virtual DWORD GetLineFlags (int nLineIndex);
+    virtual void GetText (const CPoint & ptStart, const CPoint & ptEnd, CString & text);
+
+    //  Clipboard overridable
+    virtual BOOL TextInClipboard ();
+    virtual BOOL PutToClipboard (LPCTSTR pszText);
+    virtual BOOL GetFromClipboard (CString & text);
+
+    //  Drag-n-drop overrideable
+    virtual HGLOBAL PrepareDragData ();
+    virtual DROPEFFECT GetDropEffect ();
+    virtual void OnDropSource (DROPEFFECT de);
+    BOOL IsDraggingText () const;
+
+    virtual COLORREF GetColor (int nColorIndex);
+    virtual void GetLineColors (int nLineIndex, COLORREF & crBkgnd,
+                                COLORREF & crText, BOOL & bDrawWhitespace);
+    virtual BOOL GetItalic (int nColorIndex);
+    virtual BOOL GetBold (int nColorIndex);
+
+    void DrawLineHelper (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip, int nColorIndex,
+                         LPCTSTR pszChars, int nOffset, int nCount, CPoint ptTextPos);
+    virtual void DrawSingleLine (CDC * pdc, const CRect & rect, int nLineIndex);
+    virtual void DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex);
+
+       //BEGIN SW
+       // word wrapping
+
+       /**
+       Called to wrap the line with the given index into sublines.
+
+       The standard implementation wraps the line at the first non-whitespace after
+       an whitespace that exceeds the visible line width (nMaxLineWidth). Override
+       this function to provide your own word wrapping.
+
+       <b>Attention:</b> Never call this function directly,
+       call WrapLineCached() instead, which calls this method.
+
+       @param nLineIndex The index of the line to wrap
+
+       @param nMaxLineWidth The number of characters a subline of this line should
+       not exceed (except whitespaces)
+
+       @param anBreaks An array of integers. Put the positions where to wrap the line
+       in that array (its allready allocated). If this pointer is NULL, the function
+       has only to compute the number of breaks (the parameter nBreaks).
+
+       @param nBreaks The number of breaks this line has (number of sublines - 1). When
+       the function is called, this variable is 0. If the line is not wrapped, this value
+       should be 0 after the call.
+
+       @see WrapLineCached()
+       */
+       virtual void WrapLine( int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks );
+
+       /**
+       Called to wrap the line with the given index into sublines.
+
+       Call this method instead of WrapLine() (which is called internal by this
+       method). This function uses an internal cache which contains the number
+       of sublines for each line, so it has only to call WrapLine(), if the
+       cache for the given line is invalid or if the caller wants to get the
+       wrap postions (anBreaks != NULL).
+
+       This functions also tests m_bWordWrap -- you can call it even if
+       word wrapping is disabled and you will retrieve a valid value.
+
+       @param nLineIndex The index of the line to wrap
+
+       @param nMaxLineWidth The number of characters a subline of this line should
+       not exceed (except whitespaces)
+
+       @param anBreaks An array of integers. Put the positions where to wrap the line
+       in that array (its allready allocated). If this pointer is NULL, the function
+       has only to compute the number of breaks (the parameter nBreaks).
+
+       @param nBreaks The number of breaks this line has (number of sublines - 1). When
+       the function is called, this variable is 0. If the line is not wrapped, this value
+       should be 0 after the call.
+
+       @see WrapLine()
+       @see m_anSubLines
+       */
+       void WrapLineCached( int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks );
+
+       /**
+       Invalidates the cached data for the given lines.
+
+       <b>Remarks:</b> Override this method, if your derived class caches other
+       view specific line info, which becomes invalid, when this line changes.
+       Call this standard implementation in your overriding.
+
+       @param nLineIndex1 The index of the first line to invalidate.
+
+       @param nLineIndex2 The index of the last line to invalidate. If this value is
+       -1 (default) all lines from nLineIndex1 to the end are invalidated.
+       */
+       virtual void InvalidateLineCache( int nLineIndex1, int nLineIndex2 );
+       //END SW
+
+    //  Syntax coloring overrides
+    struct TEXTBLOCK
+      {
+        int m_nCharPos;
+        int m_nColorIndex;
+      };
+
+    virtual HINSTANCE GetResourceHandle ();
+
+       //BEGIN SW
+       // function to draw a single screen line
+       // (a wrapped line can consist of many screen lines
+       virtual void DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &rcClip,
+               TEXTBLOCK *pBuf, int nBlocks, int &nActualItem,
+               COLORREF crText, COLORREF crBkgnd, BOOL bDrawWhitespace,
+               LPCTSTR pszChars,
+               int nOffset, int nCount, CPoint ptTextPos );
+       //END SW
+
+
+       //BEGIN SW
+       // helpers for incremental search
+
+       /**
+       Called each time the position-information in the status bar
+       is updated. Use this to change the text of the message field
+       in the status bar.
+
+       @param pStatusBar
+               Pointer to the status bar
+       */
+       void OnUpdateStatusMessage( CStatusBar *pStatusBar );
+
+       /**
+       Called by OnFindIncrementalForward() and OnFindIncrementalBackward().
+
+       @param bFindNextOccurence
+               TRUE, if the method should look for the next occurence of the
+               search string in search direction.
+
+       @see #OnFindIncrementalForward
+       @see #OnFindIncrementalBackward
+       */
+       void OnEditFindIncremental( BOOL bFindNextOccurence = FALSE );
+
+       /** TRUE if incremental forward search is active, FALSE otherwise */
+       BOOL m_bIncrementalSearchForward;
+
+       /** TRUE if incremental backward search is active, FALSE otherwise */
+       BOOL m_bIncrementalSearchBackward;
+
+private:
+       /** TRUE if we found the string to search for */
+       BOOL m_bIncrementalFound;
+
+       /** String we are looking for.*/
+       CString *m_pstrIncrementalSearchString;
+
+       /** String we looked for last time.*/
+       CString *m_pstrIncrementalSearchStringOld;
+
+       /** Start of selection at the time the incremental search started */
+       CPoint m_selStartBeforeIncrementalSearch;
+
+       /** Start of selection at the time the incremental search started */
+       CPoint m_selEndBeforeIncrementalSearch;
+
+       /** Cursor position at the time the incremental search started */
+       CPoint m_cursorPosBeforeIncrementalSearch;
+
+       /** position to start the incremental search at */
+       CPoint m_incrementalSearchStartPos;
+
+       //END SW
+
+public :
+    void GoToLine (int nLine, bool bRelative);
+    DWORD ParseLine (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLinePlain (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineAsp (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineBasic (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineBatch (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineC (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineDcl (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineFortran (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineHtml (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineIS (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineJava (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineLisp (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLinePascal (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLinePerl (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLinePhp (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLinePython (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineRexx (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineRsrc (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineSgml (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineSh (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineSiod (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineSql (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineTcl (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+    DWORD ParseLineTex (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+
+    // Attributes
+public :
+    int GetCRLFMode ();
+    void SetCRLFMode (int nCRLFMode);
+    BOOL GetViewTabs ();
+    void SetViewTabs (BOOL bViewTabs);
+    int GetTabSize ();
+    void SetTabSize (int nTabSize);
+    BOOL GetSelectionMargin ();
+    void SetSelectionMargin (BOOL bSelMargin);
+    void GetFont (LOGFONT & lf);
+    void SetFont (const LOGFONT & lf);
+    DWORD GetFlags ();
+    void SetFlags (DWORD dwFlags);
+    BOOL GetSmoothScroll () const;
+    void SetSmoothScroll (BOOL bSmoothScroll);
+    //  [JRT]:
+    BOOL GetDisableDragAndDrop () const;
+    void SetDisableDragAndDrop (BOOL bDDAD);
+
+       //BEGIN SW
+       BOOL GetWordWrapping() const;
+       void SetWordWrapping( BOOL bWordWrap );
+
+       /**
+       Sets the Parser to use to parse the file.
+
+       @param pParser Pointer to parser to use. Set to NULL to use no parser.
+
+       @return Pointer to parser used before or NULL, if no parser has been used before.
+       */
+       CCrystalParser *SetParser( CCrystalParser *pParser );
+       //END SW
+
+    //  Default handle to resources
+    static HINSTANCE s_hResourceInst;
+
+    int m_nLastFindWhatLen;
+    RxNode *m_rxnode;
+    RxMatchRes m_rxmatch;
+    LPTSTR m_pszMatched;
+    static LOGFONT m_LogFont;
+
+    typedef enum
+    {
+      SRC_PLAIN,
+      SRC_ASP,
+      SRC_BASIC,
+      SRC_BATCH,
+      SRC_C,
+      SRC_DCL,
+      SRC_FORTRAN,
+      SRC_HTML,
+      SRC_INSTALLSHIELD,
+      SRC_JAVA,
+      SRC_LISP,
+      SRC_PASCAL,
+      SRC_PERL,
+      SRC_PHP,
+      SRC_PYTHON,
+      SRC_REXX,
+      SRC_RSRC,
+      SRC_SGML,
+      SRC_SH,
+      SRC_SIOD,
+      SRC_SQL,
+      SRC_TCL,
+      SRC_TEX
+    }
+    TextType;
+
+    struct TextDefinition
+      {
+        TextType type;
+        TCHAR name[256];
+        TCHAR exts[256];
+        DWORD (CCrystalTextView:: * ParseLineX) (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems);
+        DWORD flags;
+        DWORD tabsize;
+        TCHAR opencomment[8];
+        TCHAR closecomment[8];
+        TCHAR commentline[8];
+        DWORD encoding;
+      };
+      
+#define SRCOPT_INSERTTABS 1
+#define SRCOPT_SHOWTABS 2
+#define SRCOPT_BSATBOL 4
+#define SRCOPT_SELMARGIN 8
+#define SRCOPT_AUTOINDENT 16
+#define SRCOPT_BRACEANSI 32
+#define SRCOPT_BRACEGNU 64
+#define SRCOPT_EOLNDOS 128
+#define SRCOPT_EOLNUNIX 256
+#define SRCOPT_EOLNMAC 512
+#define SRCOPT_FNBRACE 1024
+#define SRCOPT_WORDWRAP 2048
+
+    //  Source type
+    TextDefinition *m_CurSourceDef;
+    static TextDefinition m_SourceDefs[];
+    bool m_bRememberLastPos;
+    virtual bool DoSetTextType (TextDefinition *def);
+    static TextDefinition *GetTextType (LPCTSTR pszExt);
+    virtual bool SetTextType (LPCTSTR pszExt);
+    virtual bool SetTextType (CCrystalTextView::TextType enuType);
+    virtual bool SetTextType (CCrystalTextView::TextDefinition *def);
+    static void LoadSettings ();
+    static void SaveSettings ();
+
+    enum
+    {
+      //  Base colors
+      COLORINDEX_WHITESPACE,
+      COLORINDEX_BKGND,
+      COLORINDEX_NORMALTEXT,
+      COLORINDEX_SELMARGIN,
+      COLORINDEX_SELBKGND,
+      COLORINDEX_SELTEXT,
+      //  Syntax colors
+      COLORINDEX_KEYWORD,
+      COLORINDEX_FUNCNAME,
+      COLORINDEX_COMMENT,
+      COLORINDEX_NUMBER,
+      COLORINDEX_OPERATOR,      // [JRT]:
+      COLORINDEX_STRING,
+      COLORINDEX_PREPROCESSOR,
+      COLORINDEX_USER1,
+      COLORINDEX_USER2,
+      //  Compiler/debugger colors
+      COLORINDEX_ERRORBKGND,
+      COLORINDEX_ERRORTEXT,
+      COLORINDEX_EXECUTIONBKGND,
+      COLORINDEX_EXECUTIONTEXT,
+      COLORINDEX_BREAKPOINTBKGND,
+      COLORINDEX_BREAKPOINTTEXT
+      //  ...
+      //  Expandable: custom elements are allowed.
+    };
+
+    // Operations
+public :
+    void AttachToBuffer (CCrystalTextBuffer * pBuf = NULL);
+    void DetachFromBuffer ();
+
+    //  Buffer-view interaction, multiple views
+    virtual CCrystalTextBuffer *LocateTextBuffer ();
+    virtual void UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwFlags, int nLineIndex = -1);
+
+    //  Attributes
+    CPoint GetCursorPos ();
+    void SetCursorPos (const CPoint & ptCursorPos);
+    void ShowCursor ();
+    void HideCursor ();
+    void PopCursor ();
+    void PushCursor ();
+
+    //  Operations
+    void EnsureVisible (CPoint pt);
+
+    //  Text search helpers
+    BOOL FindText (LPCTSTR pszText, const CPoint & ptStartPos, DWORD dwFlags, BOOL bWrapSearch, CPoint * pptFoundPos);
+    BOOL FindTextInBlock (LPCTSTR pszText, const CPoint & ptStartPos, const CPoint & ptBlockBegin, const CPoint & ptBlockEnd,
+                          DWORD dwFlags, BOOL bWrapSearch, CPoint * pptFoundPos);
+    BOOL HighlightText (const CPoint & ptStartPos, int nLength, BOOL bReverse = FALSE);
+
+    //  Overridable: an opportunity for Auto-Indent, Smart-Indent etc.
+    virtual void OnEditOperation (int nAction, LPCTSTR pszText);
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CCrystalTextView)
+public :
+    virtual void OnDraw (CDC * pDC);  // overridden to draw this view
+
+    virtual BOOL PreCreateWindow (CREATESTRUCT & cs);
+    virtual BOOL PreTranslateMessage (MSG * pMsg);
+    virtual void OnPrepareDC (CDC * pDC, CPrintInfo * pInfo = NULL);
+    virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO *pHandlerInfo);
+protected :
+    virtual void OnInitialUpdate ();  // called first time after construct
+
+    virtual BOOL OnPreparePrinting (CPrintInfo * pInfo);
+    virtual void OnBeginPrinting (CDC * pDC, CPrintInfo * pInfo);
+    virtual void OnEndPrinting (CDC * pDC, CPrintInfo * pInfo);
+    virtual void OnPrint (CDC * pDC, CPrintInfo * pInfo);
+    //}}AFX_VIRTUAL
+
+    // Implementation
+public :
+    CCrystalTextView ();
+    ~CCrystalTextView ();
+
+protected :
+
+    // Generated message map functions
+protected :
+#ifdef _DEBUG
+    void AssertValidTextPos (const CPoint & pt);
+#endif
+
+    //{{AFX_MSG(CCrystalTextView)
+    afx_msg void OnDestroy ();
+    afx_msg BOOL OnEraseBkgnd (CDC * pDC);
+    afx_msg void OnSize (UINT nType, int cx, int cy);
+    afx_msg void OnVScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar);
+    afx_msg BOOL OnSetCursor (CWnd * pWnd, UINT nHitTest, UINT message);
+    afx_msg void OnLButtonDown (UINT nFlags, CPoint point);
+    afx_msg void OnSetFocus (CWnd * pOldWnd);
+    afx_msg void OnHScroll (UINT nSBCode, UINT nPos, CScrollBar * pScrollBar);
+    afx_msg void OnLButtonUp (UINT nFlags, CPoint point);
+    afx_msg void OnMouseMove (UINT nFlags, CPoint point);
+    afx_msg void OnTimer (UINT nIDEvent);
+    afx_msg void OnKillFocus (CWnd * pNewWnd);
+    afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point);
+    afx_msg void OnEditCopy ();
+    afx_msg void OnUpdateEditCopy (CCmdUI * pCmdUI);
+    afx_msg void OnEditSelectAll ();
+    afx_msg void OnUpdateEditSelectAll (CCmdUI * pCmdUI);
+    afx_msg void OnRButtonDown (UINT nFlags, CPoint point);
+    afx_msg void OnSysColorChange ();
+    afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct);
+    afx_msg void OnEditFind ();
+    afx_msg void OnEditRepeat ();
+    afx_msg void OnUpdateEditRepeat (CCmdUI * pCmdUI);
+    afx_msg void OnEditFindPrevious ();   // More search
+    afx_msg void OnEditDeleteBack();
+    afx_msg void OnChar( UINT nChar, UINT nRepCnt, UINT nFlags );
+
+    afx_msg void OnUpdateEditFindPrevious (CCmdUI * pCmdUI);
+    afx_msg BOOL OnMouseWheel (UINT nFlags, short zDelta, CPoint pt);
+    //}}AFX_MSG
+    afx_msg void OnFilePageSetup ();
+
+    afx_msg void OnCharLeft ();
+    afx_msg void OnExtCharLeft ();
+    afx_msg void OnCharRight ();
+    afx_msg void OnExtCharRight ();
+    afx_msg void OnWordLeft ();
+    afx_msg void OnExtWordLeft ();
+    afx_msg void OnWordRight ();
+    afx_msg void OnExtWordRight ();
+    afx_msg void OnLineUp ();
+    afx_msg void OnExtLineUp ();
+    afx_msg void OnLineDown ();
+    afx_msg void OnExtLineDown ();
+    afx_msg void OnPageUp ();
+    afx_msg void OnExtPageUp ();
+    afx_msg void OnPageDown ();
+    afx_msg void OnExtPageDown ();
+    afx_msg void OnLineEnd ();
+    afx_msg void OnExtLineEnd ();
+    afx_msg void OnHome ();
+    afx_msg void OnExtHome ();
+    afx_msg void OnTextBegin ();
+    afx_msg void OnExtTextBegin ();
+    afx_msg void OnTextEnd ();
+    afx_msg void OnExtTextEnd ();
+    afx_msg void OnUpdateIndicatorCRLF (CCmdUI * pCmdUI);
+    afx_msg void OnUpdateIndicatorPosition (CCmdUI * pCmdUI);
+    afx_msg void OnToggleBookmark (UINT nCmdID);
+    afx_msg void OnGoBookmark (UINT nCmdID);
+    afx_msg void OnClearBookmarks ();
+
+    afx_msg void OnToggleBookmark ();     // More bookmarks
+
+    afx_msg void OnClearAllBookmarks ();
+    afx_msg void OnNextBookmark ();
+    afx_msg void OnPrevBookmark ();
+    afx_msg void OnUpdateClearAllBookmarks (CCmdUI * pCmdUI);
+    afx_msg void OnUpdateNextBookmark (CCmdUI * pCmdUI);
+    afx_msg void OnUpdatePrevBookmark (CCmdUI * pCmdUI);
+
+    afx_msg void ScrollUp ();
+    afx_msg void ScrollDown ();
+    afx_msg void ScrollLeft ();
+    afx_msg void ScrollRight ();
+
+    afx_msg void OnSourceType (UINT nId);
+    afx_msg void OnUpdateSourceType (CCmdUI * pCmdUI);
+    afx_msg void OnMatchBrace ();
+    afx_msg void OnUpdateMatchBrace (CCmdUI * pCmdUI);
+    afx_msg void OnEditGoTo ();
+    afx_msg void OnUpdateToggleSourceHeader (CCmdUI * pCmdUI);
+    afx_msg void OnToggleSourceHeader ();
+    afx_msg void OnUpdateSelMargin (CCmdUI * pCmdUI);
+    afx_msg void OnSelMargin ();
+    afx_msg void OnUpdateWordWrap (CCmdUI * pCmdUI);
+    afx_msg void OnWordWrap ();
+    afx_msg void OnForceRedraw ();
+
+       //BEGIN SW
+       // incremental search
+       afx_msg void OnEditFindIncrementalForward();
+       afx_msg void OnEditFindIncrementalBackward();
+       afx_msg void OnUpdateEditFindIncrementalForward(CCmdUI* pCmdUI);
+       afx_msg void OnUpdateEditFindIncrementalBackward(CCmdUI* pCmdUI);
+       //END SW
+
+    DECLARE_MESSAGE_MAP ()
+  };
+
+#ifdef _DEBUG
+#define ASSERT_VALIDTEXTPOS(pt)     AssertValidTextPos(pt);
+#else
+#define ASSERT_VALIDTEXTPOS(pt)
+#endif
+
+#if ! (defined(CE_FROM_DLL) || defined(CE_DLL_BUILD))
+#include "ccrystaltextview.inl"
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CCRYSTALTEXTVIEW_H__AD7F2F41_6CB3_11D2_8C32_0080ADB86836__INCLUDED_)
diff --git a/Src/editlib/ccrystaltextview.inl b/Src/editlib/ccrystaltextview.inl
new file mode 100644 (file)
index 0000000..04d3f6b
--- /dev/null
@@ -0,0 +1,38 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       CCrystalTextView.inl
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Inline functions of Crystal Edit classes
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __CCrystalTextView_INL_INCLUDED
+#define __CCrystalTextView_INL_INCLUDED
+
+#include "CCrystalTextView.h"
+
+inline BOOL CCrystalTextView::
+IsDraggingText ()
+const
+{
+  return m_bDraggingText;
+}
+
+#endif
diff --git a/Src/editlib/ccrystaltextview2.cpp b/Src/editlib/ccrystaltextview2.cpp
new file mode 100644 (file)
index 0000000..b2b1f30
--- /dev/null
@@ -0,0 +1,1215 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ccrystaltextview2.cpp
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CCrystalTextView class, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//     21-Feb-99
+//             Paul Selormey, James R. Twine:
+//     +       FEATURE: description for Undo/Redo actions
+//     +       FEATURE: multiple MSVC-like bookmarks
+//     +       FEATURE: 'Disable backspace at beginning of line' option
+//     +       FEATURE: 'Disable drag-n-drop editing' option
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: regular expressions, go to line and things ...
+//  +   FEATURE: plenty of syntax highlighting definitions
+//  +   FEATURE: corrected bug in syntax highlighting C comments
+//  +   FEATURE: extended registry support for saving settings
+//  +   FEATURE: some other things I've forgotten ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "editcmd.h"
+#include "ccrystaltextview.h"
+#include "ccrystaltextbuffer.h"
+#include <malloc.h>
+
+#ifndef __AFXPRIV_H__
+#pragma message("Include <afxpriv.h> in your stdafx.h to avoid this message")
+#include <afxpriv.h>
+#endif
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define CRYSTAL_TIMER_DRAGSEL   1001
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCrystalTextView
+
+void CCrystalTextView::
+MoveLeft (BOOL bSelect)
+{
+  PrepareSelBounds ();
+  if (m_ptDrawSelStart != m_ptDrawSelEnd && !bSelect)
+    {
+      m_ptCursorPos = m_ptDrawSelStart;
+    }
+  else
+    {
+      if (m_ptCursorPos.x == 0)
+        {
+          if (m_ptCursorPos.y > 0)
+            {
+              m_ptCursorPos.y--;
+              m_ptCursorPos.x = GetLineLength (m_ptCursorPos.y);
+            }
+        }
+      else
+        {
+          m_ptCursorPos.x--;
+          if (m_pTextBuffer->IsMBSTrail (m_ptCursorPos.y, m_ptCursorPos.x) &&
+                // here... if its a MBSTrail, then should move one character more....
+                m_ptCursorPos.x > 0)
+            m_ptCursorPos.x--;
+        }
+    }
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveRight (BOOL bSelect)
+{
+  PrepareSelBounds ();
+  if (m_ptDrawSelStart != m_ptDrawSelEnd && !bSelect)
+    {
+      m_ptCursorPos = m_ptDrawSelEnd;
+    }
+  else
+    {
+      if (m_ptCursorPos.x == GetLineLength (m_ptCursorPos.y))
+        {
+          if (m_ptCursorPos.y < GetLineCount () - 1)
+            {
+              m_ptCursorPos.y++;
+              m_ptCursorPos.x = 0;
+            }
+        }
+      else
+        {
+          m_ptCursorPos.x++;
+          if (m_pTextBuffer->IsMBSTrail (m_ptCursorPos.y, m_ptCursorPos.x) &&
+                // here... if its a MBSTrail, then should move one character more....
+                m_ptCursorPos.x < GetLineLength (m_ptCursorPos.y))
+            m_ptCursorPos.x++;
+        }
+    }
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveWordLeft (BOOL bSelect)
+{
+  PrepareSelBounds ();
+  if (m_ptDrawSelStart != m_ptDrawSelEnd && !bSelect)
+    {
+      MoveLeft (bSelect);
+      return;
+    }
+
+  if (m_ptCursorPos.x == 0)
+    {
+      if (m_ptCursorPos.y == 0)
+        return;
+      m_ptCursorPos.y--;
+      m_ptCursorPos.x = GetLineLength (m_ptCursorPos.y);
+    }
+
+  LPCTSTR pszChars = GetLineChars (m_ptCursorPos.y);
+  int nPos = m_ptCursorPos.x;
+  while (nPos > 0 && isspace (pszChars[nPos - 1]))
+    nPos--;
+
+  if (nPos > 0)
+    {
+      nPos--;
+      if (xisalnum (pszChars[nPos]))
+        {
+          while (nPos > 0 && xisalnum (pszChars[nPos - 1]))
+            nPos--;
+        }
+      else
+        {
+          while (nPos > 0 && !xisalnum (pszChars[nPos - 1])
+                && !isspace (pszChars[nPos - 1]))
+            nPos--;
+        }
+    }
+
+  m_ptCursorPos.x = nPos;
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveWordRight (BOOL bSelect)
+{
+  PrepareSelBounds ();
+  if (m_ptDrawSelStart != m_ptDrawSelEnd && !bSelect)
+    {
+      MoveRight (bSelect);
+      return;
+    }
+
+  if (m_ptCursorPos.x == GetLineLength (m_ptCursorPos.y))
+    {
+      if (m_ptCursorPos.y == GetLineCount () - 1)
+        return;
+      m_ptCursorPos.y++;
+      m_ptCursorPos.x = 0;
+    }
+
+  int nLength = GetLineLength (m_ptCursorPos.y);
+  if (m_ptCursorPos.x == nLength)
+    {
+      MoveRight (bSelect);
+      return;
+    }
+
+  LPCTSTR pszChars = GetLineChars (m_ptCursorPos.y);
+  int nPos = m_ptCursorPos.x;
+  if (xisalnum (pszChars[nPos]))
+    {
+      while (nPos < nLength && xisalnum (pszChars[nPos]))
+        nPos++;
+    }
+  else
+    {
+      while (nPos < nLength && !xisalnum (pszChars[nPos])
+            && !isspace (pszChars[nPos]))
+        nPos++;
+    }
+
+  while (nPos < nLength && isspace (pszChars[nPos]))
+    nPos++;
+
+  m_ptCursorPos.x = nPos;
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveUp (BOOL bSelect)
+{
+  PrepareSelBounds ();
+  if (m_ptDrawSelStart != m_ptDrawSelEnd && !bSelect)
+    m_ptCursorPos = m_ptDrawSelStart;
+
+       //BEGIN SW
+       CPoint  subLinePos;
+       CharPosToPoint( m_ptCursorPos.y, m_ptCursorPos.x, subLinePos );
+
+       int                     nSubLine = GetSubLineIndex( m_ptCursorPos.y ) + subLinePos.y;
+
+       if( nSubLine > 0 )
+       /*ORIGINAL
+       if (m_ptCursorPos.y > 0)
+       *///END SW
+    {
+      if (m_nIdealCharPos == -1)
+        m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+               //BEGIN SW
+               SubLineCursorPosToTextPos( CPoint( m_nIdealCharPos, nSubLine - 1 ), m_ptCursorPos );
+               /*ORIGINAL
+               m_ptCursorPos.y --;
+               m_ptCursorPos.x = ApproxActualOffset(m_ptCursorPos.y, m_nIdealCharPos);
+               *///END SW
+      if (m_ptCursorPos.x > GetLineLength (m_ptCursorPos.y))
+        m_ptCursorPos.x = GetLineLength (m_ptCursorPos.y);
+    }
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveDown (BOOL bSelect)
+{
+  PrepareSelBounds ();
+  if (m_ptDrawSelStart != m_ptDrawSelEnd && !bSelect)
+    m_ptCursorPos = m_ptDrawSelEnd;
+
+       //BEGIN SW
+       CPoint  subLinePos;
+       CharPosToPoint( m_ptCursorPos.y, m_ptCursorPos.x, subLinePos );
+
+       int                     nSubLine = GetSubLineIndex( m_ptCursorPos.y ) + subLinePos.y;
+
+       if( nSubLine < GetSubLineCount() - 1 )
+       /*ORIGINAL
+       if (m_ptCursorPos.y < GetLineCount() - 1)
+       */
+    {
+      if (m_nIdealCharPos == -1)
+        m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+               //BEGIN SW
+               SubLineCursorPosToTextPos( CPoint( m_nIdealCharPos, nSubLine + 1 ), m_ptCursorPos );
+               /*ORIGINAL
+               m_ptCursorPos.y ++;
+               m_ptCursorPos.x = ApproxActualOffset(m_ptCursorPos.y, m_nIdealCharPos);
+               *///END SW
+      if (m_ptCursorPos.x > GetLineLength (m_ptCursorPos.y))
+        m_ptCursorPos.x = GetLineLength (m_ptCursorPos.y);
+    }
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveHome (BOOL bSelect)
+{
+  int nLength = GetLineLength (m_ptCursorPos.y);
+  LPCTSTR pszChars = GetLineChars (m_ptCursorPos.y);
+       //BEGIN SW
+       CPoint  pos;
+       CharPosToPoint( m_ptCursorPos.y, m_ptCursorPos.x, pos );
+       int nHomePos = SubLineHomeToCharPos( m_ptCursorPos.y, pos.y );
+       int nOriginalHomePos = nHomePos;
+       /*ORIGINAL
+       int nHomePos = 0;
+       *///END SW
+  while (nHomePos < nLength && isspace (pszChars[nHomePos]))
+    nHomePos++;
+  if (nHomePos == nLength || m_ptCursorPos.x == nHomePos)
+               //BEGIN SW
+               m_ptCursorPos.x = nOriginalHomePos;
+               /*ORIGINAL
+               m_ptCursorPos.x = 0;
+               *///END SW
+  else
+    m_ptCursorPos.x = nHomePos;
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveEnd (BOOL bSelect)
+{
+       //BEGIN SW
+       CPoint  pos;
+       CharPosToPoint( m_ptCursorPos.y, m_ptCursorPos.x, pos );
+       m_ptCursorPos.x = SubLineEndToCharPos( m_ptCursorPos.y, pos.y );
+       /*ORIGINAL
+       m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
+       *///END SW
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MovePgUp (BOOL bSelect)
+{
+       //BEGIN SW
+       // scrolling windows
+       int nNewTopSubLine = m_nTopSubLine - GetScreenLines() + 1;
+       if (nNewTopSubLine < 0)
+               nNewTopSubLine = 0;
+       if (m_nTopSubLine != nNewTopSubLine)
+       {
+               ScrollToSubLine(nNewTopSubLine);
+               UpdateSiblingScrollPos(TRUE);
+       }
+
+       // setting cursor
+       CPoint  subLinePos;
+       CharPosToPoint( m_ptCursorPos.y, m_ptCursorPos.x, subLinePos );
+
+       int                     nSubLine = GetSubLineIndex( m_ptCursorPos.y ) + subLinePos.y - GetScreenLines() + 1;
+
+       if( nSubLine < 0 )
+               nSubLine = 0;
+
+       SubLineCursorPosToTextPos( 
+               CPoint( m_nIdealCharPos, nSubLine ), m_ptCursorPos );
+
+       /*ORIGINAL
+       int nNewTopLine = m_nTopLine - GetScreenLines() + 1;
+       if (nNewTopLine < 0)
+               nNewTopLine = 0;
+       if (m_nTopLine != nNewTopLine)
+       {
+               ScrollToLine(nNewTopLine);
+               UpdateSiblingScrollPos(TRUE);
+       }
+
+       m_ptCursorPos.y -= GetScreenLines() - 1;
+       if (m_ptCursorPos.y < 0)
+               m_ptCursorPos.y = 0;
+       if (m_ptCursorPos.x > GetLineLength(m_ptCursorPos.y))
+               m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
+       *///END SW
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);    //todo: no vertical scroll
+
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MovePgDn (BOOL bSelect)
+{
+       //BEGIN SW
+       // scrolling windows
+       int nNewTopSubLine = m_nTopSubLine + GetScreenLines() - 1;
+       int nSubLineCount = GetSubLineCount();
+
+       if (nNewTopSubLine > nSubLineCount)
+               nNewTopSubLine = nSubLineCount - 1;
+       if (m_nTopSubLine != nNewTopSubLine)
+       {
+               ScrollToSubLine(nNewTopSubLine);
+               UpdateSiblingScrollPos(TRUE);
+       }
+
+       // setting cursor
+       CPoint  subLinePos;
+       CharPosToPoint( m_ptCursorPos.y, m_ptCursorPos.x, subLinePos );
+
+       int                     nSubLine = GetSubLineIndex( m_ptCursorPos.y ) + subLinePos.y + GetScreenLines() - 1;
+
+       if( nSubLine > nSubLineCount - 1 )
+               nSubLine = nSubLineCount - 1;
+
+       SubLineCursorPosToTextPos( 
+               CPoint( m_nIdealCharPos, nSubLine ), m_ptCursorPos );
+
+       /*ORIGINAL
+       int nNewTopLine = m_nTopLine + GetScreenLines() - 1;
+       if (nNewTopLine >= GetLineCount())
+               nNewTopLine = GetLineCount() - 1;
+       if (m_nTopLine != nNewTopLine)
+       {
+               ScrollToLine(nNewTopLine);
+               UpdateSiblingScrollPos(TRUE);
+       }
+
+       m_ptCursorPos.y += GetScreenLines() - 1;
+       if (m_ptCursorPos.y >= GetLineCount())
+               m_ptCursorPos.y = GetLineCount() - 1;
+       if (m_ptCursorPos.x > GetLineLength(m_ptCursorPos.y))
+               m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
+       *///END SW
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);    //todo: no vertical scroll
+
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveCtrlHome (BOOL bSelect)
+{
+  m_ptCursorPos.x = 0;
+  m_ptCursorPos.y = 0;
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+MoveCtrlEnd (BOOL bSelect)
+{
+  m_ptCursorPos.y = GetLineCount () - 1;
+  m_ptCursorPos.x = GetLineLength (m_ptCursorPos.y);
+  m_nIdealCharPos = CalculateActualOffset (m_ptCursorPos.y, m_ptCursorPos.x);
+  EnsureVisible (m_ptCursorPos);
+  UpdateCaret ();
+  if (!bSelect)
+    m_ptAnchor = m_ptCursorPos;
+  SetSelection (m_ptAnchor, m_ptCursorPos);
+}
+
+void CCrystalTextView::
+ScrollUp ()
+{
+  if (m_nTopLine > 0)
+    {
+      ScrollToLine (m_nTopLine - 1);
+      UpdateSiblingScrollPos (FALSE);
+    }
+}
+
+void CCrystalTextView::
+ScrollDown ()
+{
+  if (m_nTopLine < GetLineCount () - 1)
+    {
+      ScrollToLine (m_nTopLine + 1);
+      UpdateSiblingScrollPos (FALSE);
+    }
+}
+
+void CCrystalTextView::
+ScrollLeft ()
+{
+  if (m_nOffsetChar > 0)
+    {
+      ScrollToChar (m_nOffsetChar - 1);
+      UpdateCaret ();
+      UpdateSiblingScrollPos (TRUE);
+    }
+}
+
+void CCrystalTextView::
+ScrollRight ()
+{
+  if (m_nOffsetChar < GetMaxLineLength () - 1)
+    {
+      ScrollToChar (m_nOffsetChar + 1);
+      UpdateCaret ();
+      UpdateSiblingScrollPos (TRUE);
+    }
+}
+
+CPoint CCrystalTextView::
+WordToRight (CPoint pt)
+{
+  ASSERT_VALIDTEXTPOS (pt);
+  int nLength = GetLineLength (pt.y);
+  LPCTSTR pszChars = GetLineChars (pt.y);
+  while (pt.x < nLength)
+    {
+      if (!xisalnum (pszChars[pt.x]))
+        break;
+      pt.x++;
+    }
+  ASSERT_VALIDTEXTPOS (pt);
+  return pt;
+}
+
+CPoint CCrystalTextView::
+WordToLeft (CPoint pt)
+{
+  ASSERT_VALIDTEXTPOS (pt);
+  LPCTSTR pszChars = GetLineChars (pt.y);
+  while (pt.x > 0)
+    {
+      if (!xisalnum (pszChars[pt.x - 1]))
+        break;
+      pt.x--;
+    }
+  ASSERT_VALIDTEXTPOS (pt);
+  return pt;
+}
+
+void CCrystalTextView::
+SelectAll ()
+{
+  int nLineCount = GetLineCount ();
+  m_ptCursorPos.x = GetLineLength (nLineCount - 1);
+  m_ptCursorPos.y = nLineCount - 1;
+  SetSelection (CPoint (0, 0), m_ptCursorPos);
+  UpdateCaret ();
+}
+
+void CCrystalTextView::
+OnLButtonDown (UINT nFlags, CPoint point)
+{
+  CView::OnLButtonDown (nFlags, point);
+
+  BOOL bShift = GetKeyState (VK_SHIFT) & 0x8000;
+  BOOL bControl = GetKeyState (VK_CONTROL) & 0x8000;
+
+  if (point.x < GetMarginWidth ())
+    {
+      AdjustTextPoint (point);
+      if (bControl)
+        {
+          SelectAll ();
+        }
+      else
+        {
+          m_ptCursorPos = ClientToText (point);
+                       //BEGIN SW
+                       // Find char pos that is the beginning of the subline clicked on
+                       CPoint  pos;
+                       CharPosToPoint( m_ptCursorPos.y, m_ptCursorPos.x, pos );
+                       m_ptCursorPos.x = SubLineHomeToCharPos( m_ptCursorPos.y, pos.y );
+                       /*ORIGINAL
+                       m_ptCursorPos.x = 0;                            //      Force beginning of the line
+                       *///END SW
+
+          if (!bShift)
+            m_ptAnchor = m_ptCursorPos;
+
+          CPoint ptStart, ptEnd;
+                       //BEGIN SW
+                       CharPosToPoint( m_ptAnchor.y, m_ptAnchor.x, pos );
+                       ptStart.y = m_ptAnchor.y;
+                       if( GetSubLineIndex( ptStart.y ) + pos.y == GetSubLineCount() - 1 )
+                       {
+                               // select to end of subline
+                               ptStart = SubLineEndToCharPos( ptStart.y, pos.y );
+                       }
+                       else
+                       {
+                               int     nLine, nSubLine;
+                               GetLineBySubLine( GetSubLineIndex( ptStart.y ) + pos.y + 1, nLine, nSubLine );
+                               ptStart.y = nLine;
+                               ptStart.x = SubLineHomeToCharPos( nLine, nSubLine );
+                       }
+                       /*ORIGINAL
+                       ptStart = m_ptAnchor;
+                       if (ptStart.y == GetLineCount() - 1)
+                               ptStart.x = GetLineLength(ptStart.y);
+                       else
+                       {
+                               ptStart.y ++;
+                               ptStart.x = 0;
+                       }
+                       *///END SW
+
+                       //BEGIN SW
+                       ptEnd = m_ptCursorPos;
+                       /*ORIGINAL
+                       ptEnd = m_ptCursorPos;
+                       ptEnd.x = 0;
+                       *///END SW
+
+          m_ptCursorPos = ptEnd;
+          UpdateCaret ();
+          EnsureVisible (m_ptCursorPos);
+          SetSelection (ptStart, ptEnd);
+
+          SetCapture ();
+          m_nDragSelTimer = SetTimer (CRYSTAL_TIMER_DRAGSEL, 100, NULL);
+          ASSERT (m_nDragSelTimer != 0);
+          m_bWordSelection = FALSE;
+          m_bLineSelection = TRUE;
+          m_bDragSelection = TRUE;
+        }
+    }
+  else
+    {
+      CPoint ptText = ClientToText (point);
+      PrepareSelBounds ();
+      //  [JRT]:  Support For Disabling Drag and Drop...
+      if ((IsInsideSelBlock (ptText)) &&    // If Inside Selection Area
+            (!m_bDisableDragAndDrop))    // And D&D Not Disabled
+
+        {
+          m_bPreparingToDrag = TRUE;
+        }
+      else
+        {
+          AdjustTextPoint (point);
+          m_ptCursorPos = ClientToText (point);
+          if (!bShift)
+            m_ptAnchor = m_ptCursorPos;
+
+          CPoint ptStart, ptEnd;
+          if (bControl)
+            {
+              if (m_ptCursorPos.y < m_ptAnchor.y ||
+                    m_ptCursorPos.y == m_ptAnchor.y && m_ptCursorPos.x < m_ptAnchor.x)
+                {
+                  ptStart = WordToLeft (m_ptCursorPos);
+                  ptEnd = WordToRight (m_ptAnchor);
+                }
+              else
+                {
+                  ptStart = WordToLeft (m_ptAnchor);
+                  ptEnd = WordToRight (m_ptCursorPos);
+                }
+            }
+          else
+            {
+              ptStart = m_ptAnchor;
+              ptEnd = m_ptCursorPos;
+            }
+
+          m_ptCursorPos = ptEnd;
+          UpdateCaret ();
+          EnsureVisible (m_ptCursorPos);
+          SetSelection (ptStart, ptEnd);
+
+          SetCapture ();
+          m_nDragSelTimer = SetTimer (CRYSTAL_TIMER_DRAGSEL, 100, NULL);
+          ASSERT (m_nDragSelTimer != 0);
+          m_bWordSelection = bControl;
+          m_bLineSelection = FALSE;
+          m_bDragSelection = TRUE;
+        }
+    }
+
+  ASSERT_VALIDTEXTPOS (m_ptCursorPos);
+       //BEGIN SW
+       // we must set the ideal character position here!
+       m_nIdealCharPos = CalculateActualOffset( m_ptCursorPos.y, m_ptCursorPos.x );
+       //END SW
+}
+
+void CCrystalTextView::
+OnMouseMove (UINT nFlags, CPoint point)
+{
+  CView::OnMouseMove (nFlags, point);
+
+  if (m_bDragSelection)
+    {
+      BOOL bOnMargin = point.x < GetMarginWidth ();
+
+      AdjustTextPoint (point);
+      CPoint ptNewCursorPos = ClientToText (point);
+
+      CPoint ptStart, ptEnd;
+      if (m_bLineSelection)
+        {
+          if (bOnMargin)
+            {
+              if (ptNewCursorPos.y < m_ptAnchor.y ||
+                    ptNewCursorPos.y == m_ptAnchor.y && ptNewCursorPos.x < m_ptAnchor.x)
+                {
+                                       //BEGIN SW
+                                       CPoint  pos;
+                                       ptEnd = m_ptAnchor;
+                                       CharPosToPoint( ptEnd.y, ptEnd.x, pos );
+                                       if( GetSubLineIndex( ptEnd.y ) + pos.y == GetSubLineCount() - 1 )
+                                               ptEnd = SubLineEndToCharPos( ptEnd.y, pos.y );
+                                       else
+                                       {
+                                               int     nLine, nSubLine;
+                                               GetLineBySubLine( GetSubLineIndex( ptEnd.y ) + pos.y + 1, nLine, nSubLine );
+                                               ptEnd.y = nLine;
+                                               ptEnd.x = SubLineHomeToCharPos( nLine, nSubLine );
+                                       }
+                                       CharPosToPoint( ptNewCursorPos.y, ptNewCursorPos.x, pos );
+                                       ptNewCursorPos.x = SubLineHomeToCharPos( ptNewCursorPos.y, pos.y );
+                                       /*ORIGINAL
+                                       ptEnd = m_ptAnchor;
+                                       if (ptEnd.y == GetLineCount() - 1)
+                                       {
+                                               ptEnd.x = GetLineLength(ptEnd.y);
+                                       }
+                                       else
+                                       {
+                                               ptEnd.y ++;
+                                               ptEnd.x = 0;
+                                       }
+                                       ptNewCursorPos.x = 0;
+                                       *///END SW
+                  m_ptCursorPos = ptNewCursorPos;
+                }
+              else
+                {
+                  ptEnd = m_ptAnchor;
+                                       //BEGIN SW
+
+                                       CPoint  pos;
+                                       CharPosToPoint( ptEnd.y, ptEnd.x, pos );
+                                       ptEnd.x = SubLineHomeToCharPos( ptEnd.y, pos.y );
+
+                                       m_ptCursorPos = ptNewCursorPos;
+                                       CharPosToPoint( ptNewCursorPos.y, ptNewCursorPos.x, pos );
+                                       if( GetSubLineIndex( ptNewCursorPos.y ) + pos.y == GetSubLineCount() - 1 )
+                                               ptNewCursorPos.x = SubLineEndToCharPos( ptNewCursorPos.y, pos.y );
+                                       else
+                                       {
+                                               int     nLine, nSubLine;
+                                               GetLineBySubLine( GetSubLineIndex( ptNewCursorPos.y ) + pos.y + 1, nLine, nSubLine );
+                                               ptNewCursorPos.y = nLine;
+                                               ptNewCursorPos.x = SubLineHomeToCharPos( nLine, nSubLine );
+                                       }
+
+                                       int nLine, nSubLine;
+                                       GetLineBySubLine( GetSubLineIndex( m_ptCursorPos.y ) + pos.y, nLine, nSubLine );
+                                       m_ptCursorPos.y = nLine;
+                                       m_ptCursorPos.x = SubLineHomeToCharPos( nLine, nSubLine );
+                                       /*ORIGINAL
+                                       ptEnd.x = 0;
+                                       m_ptCursorPos = ptNewCursorPos;
+                                       if (ptNewCursorPos.y == GetLineCount() - 1)
+                                       {
+                                               ptNewCursorPos.x = GetLineLength(ptNewCursorPos.y);
+                                       }
+                                       else
+                                       {
+                                               ptNewCursorPos.y ++;
+                                               ptNewCursorPos.x = 0;
+                                       }
+                                       m_ptCursorPos.x = 0;
+                                       *///END SW
+                }
+              UpdateCaret ();
+              SetSelection (ptNewCursorPos, ptEnd);
+              return;
+            }
+
+          //  Moving to normal selection mode
+          ::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE (IDC_IBEAM)));
+          m_bLineSelection = m_bWordSelection = FALSE;
+        }
+
+      if (m_bWordSelection)
+        {
+          if (ptNewCursorPos.y < m_ptAnchor.y ||
+                ptNewCursorPos.y == m_ptAnchor.y && ptNewCursorPos.x < m_ptAnchor.x)
+            {
+              ptStart = WordToLeft (ptNewCursorPos);
+              ptEnd = WordToRight (m_ptAnchor);
+            }
+          else
+            {
+              ptStart = WordToLeft (m_ptAnchor);
+              ptEnd = WordToRight (ptNewCursorPos);
+            }
+        }
+      else
+        {
+          ptStart = m_ptAnchor;
+          ptEnd = ptNewCursorPos;
+        }
+
+      m_ptCursorPos = ptEnd;
+      UpdateCaret ();
+      SetSelection (ptStart, ptEnd);
+    }
+
+  if (m_bPreparingToDrag)
+    {
+      m_bPreparingToDrag = FALSE;
+      HGLOBAL hData = PrepareDragData ();
+      if (hData != NULL)
+        {
+          if (m_pTextBuffer != NULL)
+            m_pTextBuffer->BeginUndoGroup ();
+
+          COleDataSource ds;
+          ds.CacheGlobalData (CF_TEXT, hData);
+          m_bDraggingText = TRUE;
+          DROPEFFECT de = ds.DoDragDrop (GetDropEffect ());
+          if (de != DROPEFFECT_NONE)
+            OnDropSource (de);
+          m_bDraggingText = FALSE;
+
+          if (m_pTextBuffer != NULL)
+            m_pTextBuffer->FlushUndoGroup (this);
+        }
+    }
+
+  ASSERT_VALIDTEXTPOS (m_ptCursorPos);
+}
+
+void CCrystalTextView::
+OnLButtonUp (UINT nFlags, CPoint point)
+{
+  CView::OnLButtonUp (nFlags, point);
+
+  if (m_bDragSelection)
+    {
+      AdjustTextPoint (point);
+      CPoint ptNewCursorPos = ClientToText (point);
+
+      CPoint ptStart, ptEnd;
+      if (m_bLineSelection)
+        {
+          CPoint ptEnd;
+          if (ptNewCursorPos.y < m_ptAnchor.y ||
+                ptNewCursorPos.y == m_ptAnchor.y && ptNewCursorPos.x < m_ptAnchor.x)
+            {
+                               //BEGIN SW
+                               CPoint  pos;
+                               ptEnd = m_ptAnchor;
+                               CharPosToPoint( ptEnd.y, ptEnd.x, pos );
+                               if( GetSubLineIndex( ptEnd.y ) + pos.y == GetSubLineCount() - 1 )
+                                       ptEnd = SubLineEndToCharPos( ptEnd.y, pos.y );
+                               else
+                               {
+                                       int     nLine, nSubLine;
+                                       GetLineBySubLine( GetSubLineIndex( ptEnd.y ) + pos.y + 1, nLine, nSubLine );
+                                       ptEnd.y = nLine;
+                                       ptEnd.x = SubLineHomeToCharPos( nLine, nSubLine );
+                               }
+                               CharPosToPoint( ptNewCursorPos.y, ptNewCursorPos.x, pos );
+                               ptNewCursorPos.x = SubLineHomeToCharPos( ptNewCursorPos.y, pos.y );
+                               /*ORIGINAL
+                               ptEnd = m_ptAnchor;
+                               if (ptEnd.y == GetLineCount() - 1)
+                               {
+                                       ptEnd.x = GetLineLength(ptEnd.y);
+                               }
+                               else
+                               {
+                                       ptEnd.y ++;
+                                       ptEnd.x = 0;
+                               }
+                               ptNewCursorPos.x = 0;
+                               *///END SW
+              m_ptCursorPos = ptNewCursorPos;
+            }
+          else
+            {
+              ptEnd = m_ptAnchor;
+                               //BEGIN SW
+
+                               CPoint  pos;
+                               CharPosToPoint( ptEnd.y, ptEnd.x, pos );
+                               ptEnd.x = SubLineHomeToCharPos( ptEnd.y, pos.y );
+
+                               m_ptCursorPos = ptNewCursorPos;
+                               CharPosToPoint( ptNewCursorPos.y, ptNewCursorPos.x, pos );
+                               if( GetSubLineIndex( ptNewCursorPos.y ) + pos.y == GetSubLineCount() - 1 )
+                                       ptNewCursorPos.x = SubLineEndToCharPos( ptNewCursorPos.y, pos.y );
+                               else
+                               {
+                                       int     nLine, nSubLine;
+                                       GetLineBySubLine( GetSubLineIndex( ptNewCursorPos.y ) + pos.y + 1, nLine, nSubLine );
+                                       ptNewCursorPos.y = nLine;
+                                       ptNewCursorPos.x = SubLineHomeToCharPos( nLine, nSubLine );
+                               }
+                               m_ptCursorPos = ptNewCursorPos;
+                               /*ORIGINAL
+                               ptEnd.x = 0;
+                               m_ptCursorPos = ptNewCursorPos;
+                               if (ptNewCursorPos.y == GetLineCount() - 1)
+                               {
+                                       ptNewCursorPos.x = GetLineLength(ptNewCursorPos.y);
+                               }
+                               else
+                               {
+                                       ptNewCursorPos.y ++;
+                                       ptNewCursorPos.x = 0;
+                               }
+              m_ptCursorPos = ptNewCursorPos;
+                               *///END SW
+            }
+          EnsureVisible (m_ptCursorPos);
+          UpdateCaret ();
+          SetSelection (ptNewCursorPos, ptEnd);
+        }
+      else
+        {
+          if (m_bWordSelection)
+            {
+              if (ptNewCursorPos.y < m_ptAnchor.y ||
+                    ptNewCursorPos.y == m_ptAnchor.y && ptNewCursorPos.x < m_ptAnchor.x)
+                {
+                  ptStart = WordToLeft (ptNewCursorPos);
+                  ptEnd = WordToRight (m_ptAnchor);
+                }
+              else
+                {
+                  ptStart = WordToLeft (m_ptAnchor);
+                  ptEnd = WordToRight (ptNewCursorPos);
+                }
+            }
+          else
+            {
+              ptStart = m_ptAnchor;
+              ptEnd = m_ptCursorPos;
+            }
+
+          m_ptCursorPos = ptEnd;
+          EnsureVisible (m_ptCursorPos);
+          UpdateCaret ();
+          SetSelection (ptStart, ptEnd);
+        }
+
+      ReleaseCapture ();
+      KillTimer (m_nDragSelTimer);
+      m_bDragSelection = FALSE;
+    }
+
+  if (m_bPreparingToDrag)
+    {
+      m_bPreparingToDrag = FALSE;
+
+      AdjustTextPoint (point);
+      m_ptCursorPos = ClientToText (point);
+      EnsureVisible (m_ptCursorPos);
+      UpdateCaret ();
+      SetSelection (m_ptCursorPos, m_ptCursorPos);
+    }
+
+  ASSERT_VALIDTEXTPOS (m_ptCursorPos);
+}
+
+void CCrystalTextView::
+OnTimer (UINT nIDEvent)
+{
+  CView::OnTimer (nIDEvent);
+
+  if (nIDEvent == CRYSTAL_TIMER_DRAGSEL)
+    {
+      ASSERT (m_bDragSelection);
+      CPoint pt;
+      ::GetCursorPos (&pt);
+      ScreenToClient (&pt);
+      CRect rcClient;
+      GetClientRect (&rcClient);
+
+      BOOL bChanged = FALSE;
+
+      //  Scroll vertically, if necessary
+      int nNewTopLine = m_nTopLine;
+      int nLineCount = GetLineCount ();
+      if (pt.y < rcClient.top)
+        {
+          nNewTopLine--;
+          if (pt.y < rcClient.top - GetLineHeight ())
+            nNewTopLine -= 2;
+        }
+      else if (pt.y >= rcClient.bottom)
+        {
+          nNewTopLine++;
+          if (pt.y >= rcClient.bottom + GetLineHeight ())
+            nNewTopLine += 2;
+        }
+
+      if (nNewTopLine < 0)
+        nNewTopLine = 0;
+      if (nNewTopLine >= nLineCount)
+        nNewTopLine = nLineCount - 1;
+
+      if (m_nTopLine != nNewTopLine)
+        {
+          ScrollToLine (nNewTopLine);
+          UpdateSiblingScrollPos (FALSE);
+          bChanged = TRUE;
+        }
+
+      //  Scroll horizontally, if necessary
+      int nNewOffsetChar = m_nOffsetChar;
+      int nMaxLineLength = GetMaxLineLength ();
+      if (pt.x < rcClient.left)
+        nNewOffsetChar--;
+      else if (pt.x >= rcClient.right)
+        nNewOffsetChar++;
+
+      if (nNewOffsetChar >= nMaxLineLength)
+        nNewOffsetChar = nMaxLineLength - 1;
+      if (nNewOffsetChar < 0)
+        nNewOffsetChar = 0;
+
+      if (m_nOffsetChar != nNewOffsetChar)
+        {
+          ScrollToChar (nNewOffsetChar);
+          UpdateCaret ();
+          UpdateSiblingScrollPos (TRUE);
+          bChanged = TRUE;
+        }
+
+      //  Fix changes
+      if (bChanged)
+        {
+          AdjustTextPoint (pt);
+          CPoint ptNewCursorPos = ClientToText (pt);
+          if (ptNewCursorPos != m_ptCursorPos)
+            {
+              m_ptCursorPos = ptNewCursorPos;
+              UpdateCaret ();
+            }
+          SetSelection (m_ptAnchor, m_ptCursorPos);
+        }
+    }
+}
+
+void CCrystalTextView::
+OnLButtonDblClk (UINT nFlags, CPoint point)
+{
+  CView::OnLButtonDblClk (nFlags, point);
+
+  if (!m_bDragSelection)
+    {
+      AdjustTextPoint (point);
+
+      m_ptCursorPos = ClientToText (point);
+      m_ptAnchor = m_ptCursorPos;
+
+      CPoint ptStart, ptEnd;
+      if (m_ptCursorPos.y < m_ptAnchor.y ||
+            m_ptCursorPos.y == m_ptAnchor.y && m_ptCursorPos.x < m_ptAnchor.x)
+        {
+          ptStart = WordToLeft (m_ptCursorPos);
+          ptEnd = WordToRight (m_ptAnchor);
+        }
+      else
+        {
+          ptStart = WordToLeft (m_ptAnchor);
+          ptEnd = WordToRight (m_ptCursorPos);
+        }
+
+      m_ptCursorPos = ptEnd;
+      UpdateCaret ();
+      EnsureVisible (m_ptCursorPos);
+      SetSelection (ptStart, ptEnd);
+
+      SetCapture ();
+      m_nDragSelTimer = SetTimer (CRYSTAL_TIMER_DRAGSEL, 100, NULL);
+      ASSERT (m_nDragSelTimer != 0);
+      m_bWordSelection = TRUE;
+      m_bLineSelection = FALSE;
+      m_bDragSelection = TRUE;
+    }
+}
+
+void CCrystalTextView::
+OnEditCopy ()
+{
+  Copy ();
+}
+
+void CCrystalTextView::
+OnUpdateEditCopy (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (m_ptSelStart != m_ptSelEnd);
+}
+
+void CCrystalTextView::
+OnEditSelectAll ()
+{
+  SelectAll ();
+}
+
+void CCrystalTextView::
+OnUpdateEditSelectAll (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (TRUE);
+}
+
+void CCrystalTextView::
+OnRButtonDown (UINT nFlags, CPoint point)
+{
+  CPoint pt = point;
+  AdjustTextPoint (pt);
+  pt = ClientToText (pt);
+  if (!IsInsideSelBlock (pt))
+    {
+      m_ptAnchor = m_ptCursorPos = pt;
+      SetSelection (m_ptCursorPos, m_ptCursorPos);
+      EnsureVisible (m_ptCursorPos);
+      UpdateCaret ();
+    }
+
+  CView::OnRButtonDown (nFlags, point);
+}
+
+BOOL CCrystalTextView::
+IsSelection ()
+{
+  return m_ptSelStart != m_ptSelEnd;
+}
+
+void CCrystalTextView::
+Copy ()
+{
+  if (m_ptSelStart == m_ptSelEnd)
+    return;
+
+  PrepareSelBounds ();
+  CString text;
+  GetText (m_ptDrawSelStart, m_ptDrawSelEnd, text);
+  PutToClipboard (text);
+}
+
+BOOL CCrystalTextView::
+TextInClipboard ()
+{
+  return IsClipboardFormatAvailable (CF_TEXT);
+}
+
+BOOL CCrystalTextView::
+PutToClipboard (LPCTSTR pszText)
+{
+  if (pszText == NULL || _tcslen (pszText) == 0)
+    return FALSE;
+
+  CWaitCursor wc;
+  BOOL bOK = FALSE;
+  if (OpenClipboard ())
+    {
+      EmptyClipboard ();
+      HGLOBAL hData = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, _tcslen (pszText) + 1);
+      if (hData != NULL)
+        {
+          LPTSTR pszData = (LPTSTR)::GlobalLock (hData);
+          _tcscpy (pszData, (LPTSTR) pszText);
+          GlobalUnlock (hData);
+          bOK = SetClipboardData (CF_TEXT, hData) != NULL;
+        }
+      CloseClipboard ();
+    }
+  return bOK;
+}
+
+BOOL CCrystalTextView::
+GetFromClipboard (CString & text)
+{
+  BOOL bSuccess = FALSE;
+  if (OpenClipboard ())
+    {
+      HGLOBAL hData = GetClipboardData (CF_TEXT);
+      if (hData != NULL)
+        {
+          LPTSTR pszData = (LPTSTR) GlobalLock (hData);
+          if (pszData != NULL)
+            {
+              text = pszData;
+              GlobalUnlock (hData);
+              bSuccess = TRUE;
+            }
+        }
+      CloseClipboard ();
+    }
+  return bSuccess;
+}
diff --git a/Src/editlib/ceditreplacedlg.cpp b/Src/editlib/ceditreplacedlg.cpp
new file mode 100644 (file)
index 0000000..d5257e0
--- /dev/null
@@ -0,0 +1,413 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ceditreplacedlg.cpp
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CEditReplaceDlg dialog, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: regular expressions, go to line and things ...
+//  +   FEATURE: some other things I've forgotten ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ceditreplacedlg.h"
+#include "ccrystaleditview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CEditReplaceDlg dialog
+
+
+CEditReplaceDlg::CEditReplaceDlg (CCrystalEditView * pBuddy):CDialog (CEditReplaceDlg::IDD, NULL)
+{
+  ASSERT (pBuddy != NULL);
+  m_pBuddy = pBuddy;
+  //{{AFX_DATA_INIT(CEditReplaceDlg)
+  m_bMatchCase = FALSE;
+  m_bWholeWord = FALSE;
+  m_bRegExp = FALSE;
+  m_sText = _T ("");
+  m_sNewText = _T ("");
+  m_nScope = -1;
+  //}}AFX_DATA_INIT
+  m_bEnableScopeSelection = TRUE;
+}
+
+void CEditReplaceDlg::
+UpdateRegExp ()
+{
+  if (m_bRegExp)
+    {
+      m_ctlWholeWord.EnableWindow (FALSE);
+      m_bWholeWord = FALSE;
+    }
+  else
+    {
+      m_ctlWholeWord.EnableWindow (TRUE);
+    }
+}
+
+void CEditReplaceDlg::
+DoDataExchange (CDataExchange * pDX)
+{
+  CDialog::DoDataExchange (pDX);
+  //{{AFX_DATA_MAP(CEditReplaceDlg)
+  DDX_Control (pDX, IDC_EDIT_TEXT, m_ctlFindText);
+  DDX_Control (pDX, IDC_EDIT_REPLACE_WITH, m_ctlReplText);
+  DDX_Control (pDX, IDC_EDIT_WHOLE_WORD, m_ctlWholeWord);
+  DDX_Check (pDX, IDC_EDIT_MATCH_CASE, m_bMatchCase);
+  DDX_Check (pDX, IDC_EDIT_WHOLE_WORD, m_bWholeWord);
+  DDX_Check (pDX, IDC_EDIT_REGEXP, m_bRegExp);
+  DDX_CBString (pDX, IDC_EDIT_TEXT, m_sText);
+  DDX_CBString (pDX, IDC_EDIT_REPLACE_WITH, m_sNewText);
+  DDX_Radio (pDX, IDC_EDIT_SCOPE_SELECTION, m_nScope);
+  //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP (CEditReplaceDlg, CDialog)
+//{{AFX_MSG_MAP(CEditReplaceDlg)
+ON_CBN_EDITCHANGE (IDC_EDIT_TEXT, OnChangeEditText)
+ON_CBN_SELCHANGE (IDC_EDIT_TEXT, OnChangeEditText)
+ON_BN_CLICKED (IDC_EDIT_REPLACE, OnEditReplace)
+ON_BN_CLICKED (IDC_EDIT_REPLACE_ALL, OnEditReplaceAll)
+ON_BN_CLICKED (IDC_EDIT_SKIP, OnEditSkip)
+ON_BN_CLICKED (IDC_EDIT_REGEXP, OnRegExp)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+BOOL CEditReplaceDlg::PreTranslateMessage(MSG* pMsg)
+{
+  if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
+    {
+      CButton *pSkip = (CButton*) GetDlgItem (IDC_EDIT_SKIP);
+      if (pSkip->GetButtonStyle () & BS_DEFPUSHBUTTON)
+        {
+          OnEditSkip ();
+        }
+      else
+        {
+          OnEditReplace ();
+        }
+      return TRUE;
+    }
+       return CDialog::PreTranslateMessage(pMsg);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CEditReplaceDlg message handlers
+
+void CEditReplaceDlg::OnChangeEditText ()
+{
+  UpdateData();
+  GetDlgItem (IDC_EDIT_SKIP)->EnableWindow (!m_sText.IsEmpty ());
+}
+
+void CEditReplaceDlg::
+OnCancel ()
+{
+  VERIFY (UpdateData ());
+  CDialog::OnCancel ();
+}
+
+BOOL CEditReplaceDlg::
+OnInitDialog ()
+{
+  CDialog::OnInitDialog ();
+
+  m_ctlReplText.m_sGroup = _T ("ReplaceText");
+  m_ctlReplText.OnSetfocus ();
+  GetDlgItem (IDC_EDIT_REPLACE_WITH)->GetWindowText (m_sNewText);
+  UpdateData (FALSE);
+  m_ctlFindText.m_sGroup = _T ("FindText");
+  m_ctlFindText.OnSetfocus ();
+  GetDlgItem (IDC_EDIT_SKIP)->EnableWindow (!m_sText.IsEmpty ());
+  GetDlgItem (IDC_EDIT_SCOPE_SELECTION)->EnableWindow (m_bEnableScopeSelection);
+  m_bFound = FALSE;
+  UpdateRegExp ();
+
+  return TRUE;
+}
+
+BOOL CEditReplaceDlg::
+DoHighlightText ()
+{
+  ASSERT (m_pBuddy != NULL);
+  DWORD dwSearchFlags = 0;
+  if (m_bMatchCase)
+    dwSearchFlags |= FIND_MATCH_CASE;
+  if (m_bWholeWord)
+    dwSearchFlags |= FIND_WHOLE_WORD;
+  if (m_bRegExp)
+    dwSearchFlags |= FIND_REGEXP;
+
+  BOOL bFound;
+  if (m_nScope == 0)
+    {
+      //  Searching selection only
+      bFound = m_pBuddy->FindTextInBlock (m_sText, m_ptFoundAt, m_ptBlockBegin, m_ptBlockEnd,
+                                          dwSearchFlags, FALSE, &m_ptFoundAt);
+    }
+  else
+    {
+      //  Searching whole text
+      bFound = m_pBuddy->FindText (m_sText, m_ptFoundAt, dwSearchFlags, FALSE, &m_ptFoundAt);
+    }
+
+  if (!bFound)
+    {
+      CString prompt;
+      prompt.Format (IDS_EDIT_TEXT_NOT_FOUND, m_sText);
+      AfxMessageBox (prompt);
+      m_ptCurrentPos = m_nScope == 0 ? m_ptBlockBegin : CPoint (0, 0);
+      return FALSE;
+    }
+
+  m_pBuddy->HighlightText (m_ptFoundAt, m_pBuddy->m_nLastFindWhatLen);
+  return TRUE;
+}
+
+BOOL CEditReplaceDlg::
+DoReplaceText (LPCTSTR /*pszNewText*/, DWORD dwSearchFlags)
+{
+  ASSERT (m_pBuddy != NULL);
+  // m_pBuddy->m_nLastFindWhatLen
+
+  BOOL bFound;
+  if (m_nScope == 0)
+    {
+      //  Searching selection only
+      bFound = m_pBuddy->FindTextInBlock (m_sText, m_ptFoundAt, m_ptBlockBegin, m_ptBlockEnd,
+                                          dwSearchFlags, FALSE, &m_ptFoundAt);
+    }
+  else
+    {
+      //  Searching whole text
+      bFound = m_pBuddy->FindText (m_sText, m_ptFoundAt, dwSearchFlags, FALSE, &m_ptFoundAt);
+    }
+
+  if (!bFound)
+    {
+      CString prompt;
+      prompt.Format (IDS_EDIT_TEXT_NOT_FOUND, m_sText);
+      AfxMessageBox (prompt);
+      m_ptCurrentPos = m_nScope == 0 ? m_ptBlockBegin : CPoint (0, 0);
+      return FALSE;
+    }
+
+  m_pBuddy->HighlightText (m_ptFoundAt, m_pBuddy->m_nLastFindWhatLen);
+  return TRUE;
+}
+
+void CEditReplaceDlg::
+OnEditSkip ()
+{
+  if (!UpdateData ())
+    return;
+  CButton *pSkip = (CButton*) GetDlgItem (IDC_EDIT_SKIP);
+  CButton *pRepl = (CButton*) GetDlgItem (IDC_EDIT_REPLACE);
+
+  if (!m_bFound)
+    {
+      m_ptFoundAt = m_ptCurrentPos;
+      m_bFound = DoHighlightText ();
+      if (m_bFound)
+        {
+          pSkip->SetButtonStyle (pSkip->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
+          pRepl->SetButtonStyle (pRepl->GetButtonStyle () | BS_DEFPUSHBUTTON);
+          // pRepl->SetFocus ();
+        }
+      else
+        {
+          pRepl->SetButtonStyle (pRepl->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
+          pSkip->SetButtonStyle (pSkip->GetButtonStyle () | BS_DEFPUSHBUTTON);
+          // pSkip->SetFocus ();
+        }
+      return;
+    }
+
+  if (!m_pBuddy->m_nLastFindWhatLen)
+    if (m_ptFoundAt.y + 1 < m_pBuddy->GetLineCount ())
+      {
+        m_ptFoundAt.x = 0;
+        m_ptFoundAt.y++;
+      }
+    else
+      {
+        m_bFound = FALSE;
+        return;
+      }
+  else
+    m_ptFoundAt.x += 1;
+  m_bFound = DoHighlightText ();
+  if (m_bFound)
+    {
+      pSkip->SetButtonStyle (pSkip->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
+      pRepl->SetButtonStyle (pRepl->GetButtonStyle () | BS_DEFPUSHBUTTON);
+      // pRepl->SetFocus ();
+    }
+  else
+    {
+      pRepl->SetButtonStyle (pRepl->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
+      pSkip->SetButtonStyle (pSkip->GetButtonStyle () | BS_DEFPUSHBUTTON);
+      // pSkip->SetFocus ();
+    }
+}
+
+void CEditReplaceDlg::
+OnEditReplace ()
+{
+  if (!UpdateData ())
+    return;
+
+  if (!m_bFound)
+    {
+      m_ptFoundAt = m_ptCurrentPos;
+      m_bFound = DoHighlightText ();
+      CButton *pSkip = (CButton*) GetDlgItem (IDC_EDIT_SKIP);
+      CButton *pRepl = (CButton*) GetDlgItem (IDC_EDIT_REPLACE);
+      if (m_bFound)
+        {
+          pSkip->SetButtonStyle (pSkip->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
+          pRepl->SetButtonStyle (pRepl->GetButtonStyle () | BS_DEFPUSHBUTTON);
+          // pRepl->SetFocus ();
+        }
+      else
+        {
+          pRepl->SetButtonStyle (pRepl->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
+          pSkip->SetButtonStyle (pSkip->GetButtonStyle () | BS_DEFPUSHBUTTON);
+          // pSkip->SetFocus ();
+        }
+      return;
+    }
+  DWORD dwSearchFlags = 0;
+  if (m_bMatchCase)
+    dwSearchFlags |= FIND_MATCH_CASE;
+  if (m_bWholeWord)
+    dwSearchFlags |= FIND_WHOLE_WORD;
+  if (m_bRegExp)
+    dwSearchFlags |= FIND_REGEXP;
+
+  //  We have highlighted text
+  VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, dwSearchFlags));
+
+  //  Manually recalculate points
+  if (m_bEnableScopeSelection)
+    {
+      if (m_ptBlockBegin.y == m_ptFoundAt.y && m_ptBlockBegin.x > m_ptFoundAt.x)
+        {
+          m_ptBlockBegin.x -= m_pBuddy->m_nLastFindWhatLen;
+          m_ptBlockBegin.x += m_pBuddy->m_nLastReplaceLen;
+        }
+      if (m_ptBlockEnd.y == m_ptFoundAt.y && m_ptBlockEnd.x > m_ptFoundAt.x)
+        {
+          m_ptBlockEnd.x -= m_pBuddy->m_nLastFindWhatLen;
+          m_ptBlockEnd.x += m_pBuddy->m_nLastReplaceLen;
+        }
+    }
+  if (!m_pBuddy->m_nLastFindWhatLen)
+    if (m_ptFoundAt.y + 1 < m_pBuddy->GetLineCount ())
+      {
+        m_ptFoundAt.x = 0;
+        m_ptFoundAt.y++;
+      }
+    else
+      {
+        m_bFound = FALSE;
+        return;
+      }
+  else
+    {
+      m_ptFoundAt.x += m_pBuddy->m_nLastReplaceLen;
+      m_ptFoundAt = m_pBuddy->GetCursorPos ();
+    }
+  m_bFound = DoHighlightText ();
+}
+
+void CEditReplaceDlg::
+OnEditReplaceAll ()
+{
+  if (!UpdateData ())
+    return;
+
+  CWaitCursor waitCursor;
+  if (!m_bFound)
+    {
+      m_ptFoundAt = m_ptCurrentPos;
+      m_bFound = DoHighlightText ();
+    }
+
+  while (m_bFound)
+    {
+      DWORD dwSearchFlags = 0;
+      if (m_bMatchCase)
+        dwSearchFlags |= FIND_MATCH_CASE;
+      if (m_bWholeWord)
+        dwSearchFlags |= FIND_WHOLE_WORD;
+      if (m_bRegExp)
+        dwSearchFlags |= FIND_REGEXP;
+
+      //  We have highlighted text
+      VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, dwSearchFlags));
+
+      //  Manually recalculate points
+      if (m_bEnableScopeSelection)
+        {
+          if (m_ptBlockBegin.y == m_ptFoundAt.y && m_ptBlockBegin.x > m_ptFoundAt.x)
+            {
+              m_ptBlockBegin.x -= m_pBuddy->m_nLastFindWhatLen;
+              m_ptBlockBegin.x += m_pBuddy->m_nLastReplaceLen;
+            }
+          if (m_ptBlockEnd.y == m_ptFoundAt.y && m_ptBlockEnd.x > m_ptFoundAt.x)
+            {
+              m_ptBlockEnd.x -= m_pBuddy->m_nLastFindWhatLen;
+              m_ptBlockEnd.x += m_pBuddy->m_nLastReplaceLen;
+            }
+        }
+      if (!m_pBuddy->m_nLastFindWhatLen)
+        if (m_ptFoundAt.y + 1 < m_pBuddy->GetLineCount ())
+          {
+            m_ptFoundAt.x = 0;
+            m_ptFoundAt.y++;
+          }
+        else
+          {
+            m_bFound = FALSE;
+            break;
+          }
+      else
+        {
+          m_ptFoundAt.x += m_pBuddy->m_nLastReplaceLen;
+          m_ptFoundAt = m_pBuddy->GetCursorPos ();
+        }
+      m_bFound = DoHighlightText ();
+    }
+}
+
+void CEditReplaceDlg::
+OnRegExp ()
+{
+  UpdateData (TRUE);
+  UpdateRegExp ();
+  UpdateData (FALSE);
+}
diff --git a/Src/editlib/ceditreplacedlg.h b/Src/editlib/ceditreplacedlg.h
new file mode 100644 (file)
index 0000000..8ea9ed1
--- /dev/null
@@ -0,0 +1,106 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       ceditreplacedlg.h
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Declaration of the CEditReplaceDlg dialog, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CEDITREPLACEDLG_H__759417E3_7B18_11D2_8C50_0080ADB86836__INCLUDED_)
+#define AFX_CEDITREPLACEDLG_H__759417E3_7B18_11D2_8C50_0080ADB86836__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// ceditreplacedlg.h : header file
+//
+
+#include "editcmd.h"
+#include "memcombo.h"
+
+class CCrystalEditView;
+
+/////////////////////////////////////////////////////////////////////////////
+// CEditReplaceDlg dialog
+
+class EDITPADC_CLASS CEditReplaceDlg : public CDialog
+  {
+private :
+    CCrystalEditView * m_pBuddy;
+    BOOL m_bFound;
+    CPoint m_ptFoundAt;
+    BOOL DoHighlightText ();
+    BOOL DoReplaceText (LPCTSTR pszNewText, DWORD dwSearchFlags);
+
+    // Construction
+public :
+    CEditReplaceDlg (CCrystalEditView * pBuddy);
+
+    BOOL m_bEnableScopeSelection;
+    CPoint m_ptCurrentPos;
+    CPoint m_ptBlockBegin, m_ptBlockEnd;
+
+    // Dialog Data
+    //{{AFX_DATA(CEditReplaceDlg)
+       enum { IDD = IDD_EDIT_REPLACE };
+    CMemComboBox m_ctlFindText;
+    CMemComboBox m_ctlReplText;
+    CButton m_ctlWholeWord;
+    BOOL m_bMatchCase;
+    BOOL m_bWholeWord;
+    BOOL m_bRegExp;
+    CString m_sText;
+    CString m_sNewText;
+    int m_nScope;
+    //}}AFX_DATA
+
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CEditReplaceDlg)
+       public:
+       virtual BOOL PreTranslateMessage(MSG* pMsg);
+       protected:
+    virtual void DoDataExchange (CDataExchange * pDX);    // DDX/DDV support
+       //}}AFX_VIRTUAL
+
+    // Implementation
+protected :
+
+    void UpdateRegExp ();
+
+    // Generated message map functions
+    //{{AFX_MSG(CEditReplaceDlg)
+    afx_msg void OnChangeEditText ();
+    virtual void OnCancel ();
+    virtual BOOL OnInitDialog ();
+    afx_msg void OnEditReplace ();
+    afx_msg void OnEditReplaceAll ();
+    afx_msg void OnEditSkip ();
+    afx_msg void OnRegExp ();
+    //}}AFX_MSG
+    DECLARE_MESSAGE_MAP ()
+  };
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CEDITREPLACEDLG_H__759417E3_7B18_11D2_8C50_0080ADB86836__INCLUDED_)
diff --git a/Src/editlib/cfindtextdlg.cpp b/Src/editlib/cfindtextdlg.cpp
new file mode 100644 (file)
index 0000000..b7c8ac3
--- /dev/null
@@ -0,0 +1,159 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       cfindtextdlg.cpp
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CFindTextDlg dialog, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: regular expressions, go to line and things ...
+//  +   FEATURE: some other things I've forgotten ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "cfindtextdlg.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CFindTextDlg dialog
+
+CFindTextDlg::CFindTextDlg (CCrystalTextView * pBuddy):CDialog (CFindTextDlg::IDD, NULL)
+{
+  m_pBuddy = pBuddy;
+  //{{AFX_DATA_INIT(CFindTextDlg)
+  m_nDirection = 1;
+  m_bMatchCase = FALSE;
+  m_bWholeWord = FALSE;
+  m_bRegExp = FALSE;
+  m_sText = _T ("");
+  //}}AFX_DATA_INIT
+  m_ptCurrentPos = CPoint (0, 0);
+}
+
+void CFindTextDlg::
+DoDataExchange (CDataExchange * pDX)
+{
+  CDialog::DoDataExchange (pDX);
+  //{{AFX_DATA_MAP(CFindTextDlg)
+  DDX_Control (pDX, IDC_EDIT_TEXT, m_ctlFindText);
+  DDX_Control (pDX, IDC_EDIT_WHOLE_WORD, m_ctlWholeWord);
+  DDX_Radio (pDX, IDC_EDIT_DIRECTION_UP, m_nDirection);
+  DDX_Check (pDX, IDC_EDIT_MATCH_CASE, m_bMatchCase);
+  DDX_CBString (pDX, IDC_EDIT_TEXT, m_sText);
+  DDX_Check (pDX, IDC_EDIT_WHOLE_WORD, m_bWholeWord);
+  DDX_Check (pDX, IDC_EDIT_REGEXP, m_bRegExp);
+  //}}AFX_DATA_MAP
+}
+
+void CFindTextDlg::
+UpdateRegExp ()
+{
+  if (m_bRegExp)
+    {
+      m_ctlWholeWord.EnableWindow (FALSE);
+      m_bWholeWord = FALSE;
+    }
+  else
+    {
+      m_ctlWholeWord.EnableWindow (TRUE);
+    }
+}
+
+BEGIN_MESSAGE_MAP (CFindTextDlg, CDialog)
+//{{AFX_MSG_MAP(CFindTextDlg)
+ON_CBN_EDITCHANGE (IDC_EDIT_TEXT, OnChangeEditText)
+ON_CBN_SELCHANGE (IDC_EDIT_TEXT, OnChangeEditText)
+ON_BN_CLICKED (IDC_EDIT_REGEXP, OnRegExp)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+/////////////////////////////////////////////////////////////////////////////
+// CFindTextDlg message handlers
+
+void CFindTextDlg::OnOK ()
+{
+  if (UpdateData ())
+    {
+      ASSERT (m_pBuddy != NULL);
+      DWORD dwSearchFlags = 0;
+      if (m_bMatchCase)
+        dwSearchFlags |= FIND_MATCH_CASE;
+      if (m_bWholeWord)
+        dwSearchFlags |= FIND_WHOLE_WORD;
+      if (m_bRegExp)
+        dwSearchFlags |= FIND_REGEXP;
+      if (m_nDirection == 0)
+        dwSearchFlags |= FIND_DIRECTION_UP;
+
+      CPoint ptTextPos;
+      if (!m_pBuddy->FindText (m_sText, m_ptCurrentPos, dwSearchFlags, TRUE, &ptTextPos))
+        {
+          CString prompt;
+          prompt.Format (IDS_EDIT_TEXT_NOT_FOUND, m_sText);
+          AfxMessageBox (prompt);
+          m_ptCurrentPos = CPoint (0, 0);
+          return;
+        }
+
+      m_pBuddy->HighlightText (ptTextPos, m_pBuddy->m_nLastFindWhatLen, (dwSearchFlags & FIND_DIRECTION_UP) != 0);
+
+      CDialog::OnOK ();
+    }
+}
+
+void CFindTextDlg::
+OnChangeEditText ()
+{
+  UpdateData();
+  GetDlgItem (IDOK)->EnableWindow (!m_sText.IsEmpty ());
+}
+
+BOOL CFindTextDlg::
+OnInitDialog ()
+{
+  CDialog::OnInitDialog ();
+
+  UpdateData (FALSE);
+  m_ctlFindText.m_sGroup = _T ("FindText");
+  m_ctlFindText.OnSetfocus ();
+  GetDlgItem (IDOK)->EnableWindow (!m_sText.IsEmpty ());
+  UpdateRegExp ();
+
+  return TRUE;
+}
+
+void CFindTextDlg::
+OnCancel ()
+{
+  VERIFY (UpdateData ());
+  CDialog::OnCancel ();
+}
+
+void CFindTextDlg::
+OnRegExp ()
+{
+  UpdateData (TRUE);
+  UpdateRegExp ();
+  UpdateData (FALSE);
+}
diff --git a/Src/editlib/cfindtextdlg.h b/Src/editlib/cfindtextdlg.h
new file mode 100644 (file)
index 0000000..189bebe
--- /dev/null
@@ -0,0 +1,90 @@
+ ////////////////////////////////////////////////////////////////////////////
+//  File:       cfindtextdlg.h
+//  Version:    1.0.0.0
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Declaration of the CFindTextDlg dialog, a part of Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  19-Jul-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CFINDTEXTDLG_H__F59009E3_7B01_11D2_8C4F_0080ADB86836__INCLUDED_)
+#define AFX_CFINDTEXTDLG_H__F59009E3_7B01_11D2_8C4F_0080ADB86836__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "editcmd.h"
+#include "memcombo.h"
+
+class CCrystalTextView;
+
+/////////////////////////////////////////////////////////////////////////////
+// CFindTextDlg dialog
+
+class EDITPADC_CLASS CFindTextDlg : public CDialog
+  {
+private :
+    CCrystalTextView * m_pBuddy;
+
+    // Construction
+public :
+    CFindTextDlg (CCrystalTextView * pBuddy);
+
+    CPoint m_ptCurrentPos;
+    // Dialog Data
+    //{{AFX_DATA(CFindTextDlg)
+       enum { IDD = IDD_EDIT_FIND };
+    CMemComboBox m_ctlFindText;
+    CButton m_ctlWholeWord;
+    int m_nDirection;
+    BOOL m_bMatchCase;
+    CString m_sText;
+    BOOL m_bWholeWord;
+    BOOL m_bRegExp;
+    //}}AFX_DATA
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CFindTextDlg)
+protected :
+    virtual void DoDataExchange (CDataExchange * pDX);    // DDX/DDV support
+    //}}AFX_VIRTUAL
+
+    // Implementation
+protected :
+
+    void UpdateRegExp ();
+
+    // Generated message map functions
+    //{{AFX_MSG(CFindTextDlg)
+    virtual void OnOK ();
+    afx_msg void OnChangeEditText ();
+    virtual BOOL OnInitDialog ();
+    virtual void OnCancel ();
+    afx_msg void OnRegExp ();
+    //}}AFX_MSG
+    DECLARE_MESSAGE_MAP ()
+  };
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CFINDTEXTDLG_H__F59009E3_7B01_11D2_8C4F_0080ADB86836__INCLUDED_)
diff --git a/Src/editlib/chcondlg.cpp b/Src/editlib/chcondlg.cpp
new file mode 100644 (file)
index 0000000..ba4a257
--- /dev/null
@@ -0,0 +1,126 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    chcondlg.cpp
+//  Version: 1.6.0.9
+//  Updated: 17-Oct-1999
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Character encoding dialog
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "chcondlg.h"
+#include "ccrystaltextview.h"
+#include "cs2cs.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+EDITPADC_CLASS LPCTSTR pszCodeNames[] =
+  {
+    _T ("ASCII (without accents)"),
+    _T ("MS-Windows CP 1250"),
+    _T ("MS-Windows CP 1252"),
+    _T ("PC Latin I (CP 850)"),
+    _T ("PC Latin II (CP 852)"),
+    _T ("IBM Latin II (IBM 852)"),
+    _T ("ISO-8859-1"),
+    _T ("ISO-8859-2"),
+    _T ("Brothers Kamenicky"),
+    _T ("KOI8-CS"),
+    _T ("Apple Macintosh"),
+    _T ("Apple Macintosh for Central Europe"),
+    _T ("Corky"),
+    NULL
+  };
+
+EDITPADC_CLASS int nCodeNames = countof (pszCodeNames) - 1;
+
+EDITPADC_CLASS void FillComboBox (CComboBox &Control, LPCTSTR *pszItems)
+{
+  Control.ResetContent();
+  ASSERT (pszItems);
+  while (*pszItems)
+    Control.AddString(*pszItems++);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CCharConvDlg dialog
+
+CCharConvDlg::CCharConvDlg () : CDialog (CCharConvDlg::IDD, NULL)
+{
+  //{{AFX_DATA_INIT(CCharConvDlg)
+       m_nSource = 1;
+       m_nDest = 1;
+       m_bAlpha = FALSE;
+       m_sPreview = _T("");
+       //}}AFX_DATA_INIT
+}
+
+void CCharConvDlg::
+DoDataExchange (CDataExchange * pDX)
+{
+  CDialog::DoDataExchange (pDX);
+  //{{AFX_DATA_MAP(CCharConvDlg)
+       DDX_Control(pDX, IDC_SRC, m_ctlSource);
+       DDX_Control(pDX, IDC_DEST, m_ctlDest);
+       DDX_CBIndex(pDX, IDC_SRC, m_nSource);
+       DDX_CBIndex(pDX, IDC_DEST, m_nDest);
+       DDX_Check(pDX, IDC_ALPHA_ONLY, m_bAlpha);
+       DDX_Text(pDX, IDC_PREVIEW, m_sPreview);
+       //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP (CCharConvDlg, CDialog)
+//{{AFX_MSG_MAP(CCharConvDlg)
+       ON_BN_CLICKED(IDPREVIEW, OnPreview)
+       //}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCharConvDlg message handlers
+
+static int nSource = 1;
+static int nDest = 1;
+
+BOOL CCharConvDlg::
+OnInitDialog ()
+{
+  CDialog::OnInitDialog ();
+  FillComboBox (m_ctlSource, pszCodeNames);
+  FillComboBox (m_ctlDest, pszCodeNames);
+       m_nSource = nSource;
+       m_nDest = nSource;
+  m_sPreview = m_sOriginal;
+  UpdateData (FALSE);
+  return TRUE;
+}
+
+void CCharConvDlg::OnOK ()
+{
+  CDialog::OnOK ();
+       nSource = m_nSource;
+       nDest = m_nSource;
+}
+
+void CCharConvDlg::OnPreview() 
+{
+  UpdateData ();
+  LPTSTR pszNew;
+  if (!iconvert_new (m_sOriginal, &pszNew, m_nSource, m_nDest, m_bAlpha != FALSE))
+    {
+      m_sPreview = pszNew;
+      UpdateData (FALSE);
+    }
+  if (pszNew)
+    free (pszNew);
+}
diff --git a/Src/editlib/chcondlg.h b/Src/editlib/chcondlg.h
new file mode 100644 (file)
index 0000000..fd1dd73
--- /dev/null
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    chcondlg.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Character encoding dialog
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __CHCONDLG_H__INCLUDED__
+#define __CHCONDLG_H__INCLUDED__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "editcmd.h"
+
+class CCrystalTextView;
+
+/////////////////////////////////////////////////////////////////////////////
+// CCharConvDlg dialog
+
+class EDITPADC_CLASS CCharConvDlg : public CDialog
+  {
+    // Construction
+public :
+    CCharConvDlg ();
+
+    // Dialog Data
+    //{{AFX_DATA(CCharConvDlg)
+       enum { IDD = IDD_EDIT_CHARCONV };
+       CComboBox       m_ctlSource;
+       CComboBox       m_ctlDest;
+       int             m_nSource;
+       int             m_nDest;
+       BOOL    m_bAlpha;
+       CString m_sPreview;
+       //}}AFX_DATA
+       CString m_sOriginal;
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CCharConvDlg)
+protected :
+    virtual void DoDataExchange (CDataExchange * pDX);    // DDX/DDV support
+    //}}AFX_VIRTUAL
+
+    // Implementation
+protected :
+
+    // Generated message map functions
+    //{{AFX_MSG(CCharConvDlg)
+    virtual void OnOK ();
+    virtual BOOL OnInitDialog ();
+       afx_msg void OnPreview();
+       //}}AFX_MSG
+    DECLARE_MESSAGE_MAP ()
+  };
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // __CHCONDLG_H__INCLUDED__
diff --git a/Src/editlib/cplusplus.cpp b/Src/editlib/cplusplus.cpp
new file mode 100644 (file)
index 0000000..6a1b9e1
--- /dev/null
@@ -0,0 +1,489 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:       cplusplus.cpp
+//  Version:    1.2.0.5
+//  Created:    29-Dec-1998
+//
+//  Copyright:  Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CCrystalEditView class, a part of the Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  16-Aug-99
+//      Ferdinand Prantl:
+//  +   FEATURE: corrected bug in syntax highlighting C comments
+//  +   FEATURE: extended levels 1- 4 of keywords in some languages
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszCppKeywordList[] =
+  {
+    _T ("_asm"),
+    _T ("__asm"),
+    _T ("_far16"),
+    _T ("__far16"),
+    _T ("enum"),
+    _T ("__multiple_inheritance"),
+    _T ("template"),
+    _T ("auto"),
+    _T ("__except"),
+    _T ("__single_inheritance"),
+    _T ("this"),
+    _T ("__based"),
+    _T ("explicit"),
+    _T ("__virtual_inheritance"),
+    _T ("thread"),
+    _T ("bool"),
+    _T ("extern"),
+    _T ("mutable"),
+    _T ("throw"),
+    _T ("break"),
+    _T ("false"),
+    _T ("naked"),
+    _T ("true"),
+    _T ("case"),
+    _T ("_fastcall"),
+    _T ("__fastcall"),
+    _T ("namespace"),
+    _T ("try"),
+    _T ("catch"),
+    _T ("__finally"),
+    _T ("new"),
+    _T ("__try"),
+    _T ("__cdecl"),
+    _T ("__pascal"),
+    _T ("_cdecl"),
+    _T ("_pascal"),
+    _T ("float"),
+    _T ("operator"),
+    _T ("typedef"),
+    _T ("char"),
+    _T ("for"),
+    _T ("private"),
+    _T ("typeid"),
+    _T ("class"),
+    _T ("friend"),
+    _T ("protected"),
+    _T ("typename"),
+    _T ("const"),
+    _T ("goto"),
+    _T ("public"),
+    _T ("union"),
+    _T ("const_cast"),
+    _T ("if"),
+    _T ("register"),
+    _T ("unsigned"),
+    _T ("continue"),
+    _T ("inline"),
+    _T ("reinterpret_cast"),
+    _T ("using"),
+    _T ("__declspec"),
+    _T ("__inline"),
+    _T ("return"),
+    _T ("uuid"),
+    _T ("default"),
+    _T ("int"),
+    _T ("short"),
+    _T ("__uuidof"),
+    _T ("delete"),
+    _T ("__int8"),
+    _T ("signed"),
+    _T ("virtual"),
+    _T ("_export"),
+    _T ("__export"),
+    _T ("dllexport"),
+    _T ("__int16"),
+    _T ("sizeof"),
+    _T ("void"),
+    _T ("dllimport"),
+    _T ("__int32"),
+    _T ("static"),
+    _T ("volatile"),
+    _T ("do"),
+    _T ("__int64"),
+    _T ("static_cast"),
+    _T ("wmain"),
+    _T ("double"),
+    _T ("__leave"),
+    _T ("_stdcall"),
+    _T ("__stdcall"),
+    _T ("_syscall"),
+    _T ("__syscall"),
+    _T ("while"),
+    _T ("dynamic_cast"),
+    _T ("long"),
+    _T ("struct"),
+    _T ("xalloc"),
+    _T ("else"),
+    _T ("main"),
+    _T ("switch"),
+    _T ("interface"),
+    //  Added by a.s.
+    _T ("persistent"),
+    _T ("_persistent"),
+    _T ("transient"),
+    _T ("depend"),
+    _T ("ondemand"),
+    _T ("transient"),
+    _T ("cset"),
+    _T ("useindex"),
+    _T ("indexdef"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("LPTSTR"),
+    _T ("LPCTSTR"),
+    _T ("LPWSTR"),
+    _T ("LPCWSTR"),
+    _T ("LPTSTR"),
+    _T ("LPCTSTR"),
+    _T ("CHAR"),
+    _T ("WCHAR"),
+    _T ("TCHAR"),
+    _T ("BYTE"),
+    _T ("BOOL"),
+    _T ("TRUE"),
+    _T ("FALSE"),
+    _T ("INT"),
+    _T ("UINT"),
+    _T ("WORD"),
+    _T ("DWORD"),
+    _T ("WPARAM"),
+    _T ("LPARAM"),
+    _T ("LRESULT"),
+    _T ("CString"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsncmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsCppKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszCppKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsCppNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineC (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Preprocessor directive #....
+      if (dwCookie & COOKIE_PREPROCESSOR)
+        {
+          if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+            {
+              DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+              dwCookie |= COOKIE_EXT_COMMENT;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (pszChars[I] == '#')
+            {
+              DEFINE_BLOCK (I, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              continue;
+            }
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsCppKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsCppNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsCppKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsCppNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/cregexp.cpp b/Src/editlib/cregexp.cpp
new file mode 100644 (file)
index 0000000..18dccf8
--- /dev/null
@@ -0,0 +1,1159 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    regexp.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Marko Macek
+//  E-mail:     Marko.Macek@gmx.net or mark@hermes.si
+//
+//  Some handy stuff to deal with regular expressions
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "cregexp.h"
+
+//#define DEBUG
+
+static int RegCount = 0;
+
+#ifdef DEBUG
+static void RxDump(int N, RxNode *n);
+#endif
+
+static  RxNode *NewNode(int aWhat) {
+    RxNode *N = (RxNode *) malloc(sizeof(RxNode));
+
+    if (N) {
+        memset(N, 0, sizeof(RxNode));
+        N->fWhat = (short)aWhat;
+    }
+    return N;
+}
+
+static RxNode *NewChar(TCHAR Ch) {
+    RxNode *A = NewNode(RE_CHAR);
+
+    if (A) {
+        A->fChar = (LPTSTR) malloc(1);
+        A->fLen = 1;
+        A->fChar[0] = Ch;
+    }
+    return A;
+}
+
+static RxNode *NewEscape(LPCTSTR *const Regexp) {
+    TCHAR Ch = **Regexp;
+    ++*Regexp;
+    switch (Ch) {
+      case 0: return 0;
+      case _T('a'): Ch = _T('\a'); break;
+      case _T('b'): Ch = _T('\b'); break;
+      case _T('f'): Ch = _T('\f'); break;
+      case _T('n'): Ch = _T('\n'); break;
+      case _T('r'): Ch = _T('\r'); break;
+      case _T('t'): Ch = _T('\t'); break;
+      case _T('v'): Ch = _T('\v'); break;
+      case _T('e'): Ch = 27; break;
+      case _T('s'): return NewNode(RE_WSPACE);
+      case _T('S'): return NewNode(RE_NWSPACE);
+      case _T('U'): return NewNode(RE_UPPER);
+      case _T('L'): return NewNode(RE_LOWER);
+      case _T('w'): return NewNode(RE_WORD);
+      case _T('W'): return NewNode(RE_NWORD);
+      case _T('d'): return NewNode(RE_DIGIT);
+      case _T('D'): return NewNode(RE_NDIGIT);
+      case _T('C'): return NewNode(RE_CASE);
+      case _T('c'): return NewNode(RE_NCASE);
+      case _T('N'):
+        {
+            unsigned int N = 0;
+            unsigned int A = 0;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 9) return 0;
+            (*Regexp)++;
+            A = N * 100;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 9) return 0;
+            (*Regexp)++;
+            A = A + N * 10;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 9) return 0;
+            (*Regexp)++;
+            A = A + N;
+            Ch = (TCHAR) A;
+        }
+        break;
+    case _T('o'):
+        {
+            unsigned int N = 0;
+            unsigned int A = 0;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 7) return 0;
+            (*Regexp)++;
+            A = N * 64;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 7) return 0;
+            (*Regexp)++;
+            A = A + N * 8;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 7) return 0;
+            (*Regexp)++;
+            A = A + N;
+            Ch = (TCHAR) A;
+        }
+        break;
+    case _T('x'):
+        {
+            unsigned int N = 0;
+            unsigned int A = 0;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
+            (*Regexp)++;
+            A = N << 4;
+            if (**Regexp == 0) return 0;
+            N = _totupper(**Regexp) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
+            (*Regexp)++;
+            A = A + N;
+            Ch = (TCHAR) A;
+        }
+        break;
+    }
+    return NewChar(Ch);
+}
+
+
+#define NNN 32        // 8 * 32 = 256 (match set)
+
+#ifdef _UNICODE
+#define SETOP(set,n) \
+    do { \
+      set[(TCHAR)(n) >> 3] |= (TCHAR)(1 << ((TCHAR)(n) & 7)); \
+    } while (0)
+#else // _UNICODE
+#define SETOP(set,n) \
+    do { \
+      set[(unsigned char)(n) >> 3] |= (unsigned char)(1 << ((unsigned char)(n) & 7)); \
+    } while (0)
+#endif // _UNICODE
+
+static RxNode *NewSet(LPCTSTR * const Regexp) {
+#ifdef _UNICODE
+    TCHAR set[NNN];
+#else // _UNICODE
+    unsigned char set[NNN];
+#endif // _UNICODE
+    int s = 0;
+    int c = 0;
+    unsigned int i, xx;
+#ifdef _UNICODE
+    TCHAR Ch, C1 = 0, C2 = 0;
+#else // _UNICODE
+    unsigned char Ch, C1 = 0, C2 = 0;
+#endif // _UNICODE
+    int doset = 0;
+
+    memset(set, 0, sizeof(set));
+    s = 1;
+    if (**Regexp == _T('^')) {
+        s = 0;
+        ++*Regexp;
+    }
+    c = 0;
+
+    while (**Regexp) {
+        switch (Ch = *((*Regexp)++)) {
+          case _T(']'):
+            if (doset == 1) return 0;
+            {
+                RxNode *N = NewNode(s?RE_INSET:RE_NOTINSET);
+                N->fChar = (LPTSTR) malloc(sizeof(set));
+                N->fLen = sizeof(set);
+                if (N->fChar == 0) return 0;
+                memcpy(N->fChar, (LPTSTR) set, sizeof(set));
+                return N;
+            }
+          case _T('\\'):
+            switch (Ch = *((*Regexp)++)) {
+              case 0: return 0;
+              case _T('a'): Ch = _T('\a'); break;
+              case _T('b'): Ch = _T('\b'); break;
+              case _T('f'): Ch = _T('\f'); break;
+              case _T('n'): Ch = _T('\n'); break;
+              case _T('r'): Ch = _T('\r'); break;
+              case _T('t'): Ch = _T('\t'); break;
+              case _T('v'): Ch = _T('\v'); break;
+              case _T('e'): Ch = 27; break;
+              case _T('N'):
+                  {
+                      unsigned int N = 0;
+                      unsigned int A = 0;
+                      if (**Regexp == 0) return 0;
+                      N = _totupper(**Regexp) - 48; if (N > 9) return 0;
+                      (*Regexp)++;
+                      A = N * 100;
+                      if (**Regexp == 0) return 0;
+                      N = _totupper(**Regexp) - 48; if (N > 9) return 0;
+                      (*Regexp)++;
+                      A = A + N * 10;
+                      if (**Regexp == 0) return 0;
+                      N = _totupper(**Regexp) - 48; if (N > 9) return 0;
+                      (*Regexp)++;
+                      A = A + N;
+#ifdef _UNICODE
+                      Ch = (TCHAR)A;
+#else // _UNICODE
+                      Ch = (unsigned char)A;
+#endif // _UNICODE
+                  }
+                  break;
+            case _T('o'):
+                {
+                    unsigned int N = 0;
+                    unsigned int A = 0;
+                    if (**Regexp == 0) return 0;
+                    N = _totupper(**Regexp) - 48; if (N > 7) return 0;
+                    (*Regexp)++;
+                    A = N * 64;
+                    if (**Regexp == 0) return 0;
+                    N = _totupper(**Regexp) - 48; if (N > 7) return 0;
+                    (*Regexp)++;
+                    A = A + N * 8;
+                    if (**Regexp == 0) return 0;
+                    N = _totupper(**Regexp) - 48; if (N > 7) return 0;
+                    (*Regexp)++;
+                    A = A + N;
+#ifdef _UNICODE
+                    Ch = (TCHAR)A;
+#else // _UNICODE
+                    Ch = (unsigned char)A;
+#endif // _UNICODE
+                }
+                break;
+            case _T('x'):
+                {
+                    unsigned int N = 0;
+                    unsigned int A = 0;
+                    if (**Regexp == 0) return 0;
+                    N = _totupper(**Regexp) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
+                    (*Regexp)++;
+                    A = N << 4;
+                    if (**Regexp == 0) return 0;
+                    N = _totupper(**Regexp) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
+                    (*Regexp)++;
+                    A = A + N;
+#ifdef _UNICODE
+                    Ch = (TCHAR)A;
+#else // _UNICODE
+                    Ch = (unsigned char)A;
+#endif // _UNICODE
+                }
+                break;
+            case _T('s'):
+                c += 4;
+                SETOP(set, _T('\n'));
+                SETOP(set, _T('\t'));
+                SETOP(set, _T(' '));
+                SETOP(set, _T('\r'));
+                continue;
+            case _T('S'):
+                for (xx = 0; xx <= 255; xx++) {
+                    if (xx != _T(' ') && xx != _T('\t') && xx != _T('\n') && xx != _T('\r')) {
+                        c++;
+                        SETOP(set, xx);
+                    }
+                }
+                continue;
+            case _T('w'):
+                for (xx = 0; xx <= 255; xx++) {
+                    if (_istalnum(xx)) {
+                        c++;
+                        SETOP(set, xx);
+                    }
+                }
+                break;
+            case _T('W'):
+                for (xx = 0; xx <= 255; xx++) {
+                    if (!isalnum(xx)) {
+                        c++;
+                        SETOP(set, xx);
+                    }
+                }
+                break;
+            case _T('d'):
+                for (xx = 0; xx <= 255; xx++) {
+                    if (_istdigit(xx)) {
+                        c++;
+                        SETOP(set, xx);
+                    }
+                }
+                break;
+            case _T('D'):
+                for (xx = 0; xx <= 255; xx++) {
+                    if (!_istdigit(xx)) {
+                        c++;
+                        SETOP(set, xx);
+                    }
+                }
+                break;
+            case _T('U'):
+                for (xx = _T('A'); xx <= _T('Z'); xx++) {
+                    c++;
+                    SETOP(set, xx);
+                }
+                continue;
+            case _T('L'):
+                for (xx = _T('a'); xx <= _T('z'); xx++) {
+                    c++;
+                    SETOP(set, xx);
+                }
+                continue;
+            }
+            break;
+        }
+        if (doset == 0 && ((**Regexp) == _T('-'))) {
+            doset = 1;
+            C1 = Ch;
+            ++*Regexp;
+            continue;
+        } else if (doset == 1) {
+            C2 = Ch;
+            if (C2 < C1) return 0;
+            for(i = C1; i <= C2; i++) SETOP(set, i);
+            doset = 0;
+            continue;
+        }
+        c++;
+        SETOP(set, Ch);
+    }
+    return 0;
+}
+
+static int AddNode(RxNode **F, RxNode **N, RxNode *A) {
+    if (A) {
+        if (*F) {
+            (*N)->fNext = A;
+            A->fPrev = (*N);
+            *N = A;
+        } else {
+            (*N) = (*F) = A;
+            A->fPrev = A->fNext = 0;
+        }
+        return 1;
+    }
+    return 0;
+}
+
+static int CountWidth(RxNode *N) {
+    int w = 0;
+
+    while (N) {
+        if (N->fWhat < 32) w += 0;
+        else if (N->fWhat >= 32 && N->fWhat < 64)
+            w += 1;
+        N = N->fNext;
+    }
+    return w;
+}
+
+static int MakeSub(RxNode **F, RxNode **N, TCHAR What) {
+    //_tprintf(_T("MakeSub: %c\n", What));
+    if (*N) {
+        RxNode *No;
+        RxNode *New;
+        RxNode *Jump, *Skip;
+        RxNode *Last = (*N);
+
+        if (Last->fWhat & RE_GROUP) {
+            RxNode *P = Last->fPrev;
+            int C = 1;
+
+            while ((C > 0) && P) {
+                //puts(_T("backtracking...-----"));
+                //RxDump(0, P);
+                if (P->fWhat & RE_GROUP) {
+                    if (P->fWhat & RE_CLOSE) C++;
+                    else C--;
+                }
+                Last = P;
+                if (C == 0) break;
+                P = P->fPrev;
+            }
+            //_tprintf(_T("P = %s, c = %d", P ? "ok":"null", C));
+            if (C != 0) return 0;
+        }
+        assert(Last);
+        if (What != _T('?') && What != _T('|'))
+            if (CountWidth(Last) == 0) {
+                //                puts(_T("FAILED count"));
+                return 0;
+            }
+        switch (What) {
+        case _T('?'):    /* BRANCH x NOTHING */
+            New = NewNode(RE_BRANCH | RE_GREEDY | What);
+            No = NewNode(RE_NOTHING);
+            if (!New || !No) return 0;
+            No->fPrev = *N;
+            if (*N)
+                (*N)->fNext = No;
+            New->fNext = Last;
+            New->fPrev = Last->fPrev;
+            Last->fPrev = New;
+            if (New->fPrev) {
+                New->fPrev->fNext = New;
+            } else {
+                *F = New;
+            }
+            New->fPtr = No;
+            No->fPtr = New;
+            *N = No;
+            //puts(_T("BRANCH ?"));
+            break;
+
+        case _T('*'):
+        case _T('@'):
+            New = NewNode(RE_BRANCH | What | ((What == _T('*')) ? RE_GREEDY : 0));
+            Jump = NewNode(RE_JUMP);
+            No = NewNode(RE_NOTHING);
+
+            if (!New || !No || !Jump) return 0;
+            No->fPrev = Jump;
+            Jump->fNext = No;
+            Jump->fPrev = *N;
+            if (*N)
+                (*N)->fNext = Jump;
+            New->fNext = Last;
+            New->fPrev = Last->fPrev;
+            Last->fPrev = New;
+            if (New->fPrev) {
+                New->fPrev->fNext = New;
+            } else {
+                *F = New;
+            }
+            New->fPtr = No;
+            No->fPtr = New;
+            Jump->fPtr = New;
+            *N = No;
+            //puts(_T("BRANCH *"));
+            break;
+
+        case _T('#'):
+        case _T('+'):
+            New = NewNode(RE_BRANCH | What | ((What == _T('+')) ? RE_GREEDY : 0));
+            Skip = NewNode(RE_JUMP);
+            Jump = NewNode(RE_JUMP);
+            No = NewNode(RE_NOTHING);
+
+            if (!New || !No || !Jump) return 0;
+            No->fPrev = Jump;
+            Jump->fPrev = *N;
+            Jump->fNext = No;
+
+            Skip->fNext = New;
+            New->fPrev = Skip;
+            if (*N)
+                (*N)->fNext = Jump;
+            New->fNext = Last;
+            Skip->fPrev = Last->fPrev;
+            Last->fPrev = New;
+            if (Skip->fPrev) {
+                Skip->fPrev->fNext = Skip;
+            } else {
+                *F = Skip;
+            }
+            New->fPtr = No;
+            No->fPtr = New;
+            Jump->fPtr = New;
+            Skip->fPtr = Last;
+            *N = No;
+            //puts(_T("BRANCH +"));
+            break;
+        case _T('|'):
+            New = NewNode(RE_BRANCH | RE_GREEDY | What);
+            Jump = NewNode(RE_BREAK);
+            No = NewNode(RE_NOTHING);
+
+            if (!New || !No || !Jump) return 0;
+            No->fPrev = Jump;
+            Jump->fNext = No;
+            Jump->fPrev = *N;
+            if (*N)
+                (*N)->fNext = Jump;
+            New->fNext = Last;
+            New->fPrev = Last->fPrev;
+            Last->fPrev = New;
+            if (New->fPrev) {
+                New->fPrev->fNext = New;
+            } else {
+                *F = New;
+            }
+            New->fPtr = No;
+            No->fPtr = New;
+            Jump->fPtr = New;
+            *N = No;
+            //puts(_T("BRANCH |"));
+            break;
+        }
+        return 1;
+    }
+    return 0;
+}
+
+#define CHECK(n) do { if ((n) == 0) { return 0;} } while (0)
+
+static RxNode *RxComp(LPCTSTR *Regexp) {
+    RxNode *F = 0;
+    RxNode *N = 0;
+    int C;
+    TCHAR Ch;
+
+    while (**Regexp) {
+        //        puts(*Regexp);
+        switch (Ch = (*(*Regexp)++)) {
+        case _T('?'):
+        case _T('*'):
+        case _T('+'):
+        case _T('@'):
+        case _T('#'):
+        case _T('|'):
+            CHECK(MakeSub(&F, &N, Ch));
+            break;
+        case _T('}'):
+        case _T(')'):
+            return F;
+        case _T('{'):
+            CHECK(AddNode(&F, &N, NewNode(RE_GROUP | RE_OPEN)));
+            CHECK(AddNode(&F, &N, RxComp(Regexp)));
+            while (N->fNext) N = N->fNext;
+            CHECK(AddNode(&F, &N, NewNode(RE_GROUP | RE_CLOSE)));
+            break;
+        case _T('('):
+            C = ++RegCount;
+            CHECK(AddNode(&F, &N, NewNode(RE_GROUP | RE_OPEN | RE_MEM | C)));
+            CHECK(AddNode(&F, &N, RxComp(Regexp)));
+            while (N->fNext) N = N->fNext;
+            CHECK(AddNode(&F, &N, NewNode(RE_GROUP | RE_CLOSE | RE_MEM | C)));
+            break;
+        case _T('\\'):CHECK(AddNode(&F, &N, NewEscape(Regexp)));     break;
+        case _T('['): CHECK(AddNode(&F, &N, NewSet(Regexp)));        break;
+        case _T('^'): CHECK(AddNode(&F, &N, NewNode(RE_ATBOL)));     break;
+        case _T('$'): CHECK(AddNode(&F, &N, NewNode(RE_ATEOL)));     break;
+        case _T('.'): CHECK(AddNode(&F, &N, NewNode(RE_ANY)));       break;
+        case _T('<'): CHECK(AddNode(&F, &N, NewNode(RE_ATBOW)));     break;
+        case _T('>'): CHECK(AddNode(&F, &N, NewNode(RE_ATEOW)));     break;
+        default:
+            --*Regexp;
+            CHECK(AddNode(&F, &N, NewChar(**Regexp)));
+            ++*Regexp;
+            break;
+        }
+    }
+    return F;
+}
+
+RxNode *RxOptimize(RxNode *rx) {
+    return rx;
+}
+
+RxNode *RxCompile(LPCTSTR Regexp) {
+    RxNode *n = 0, *x;
+    if (Regexp == 0) return 0;
+    RegCount = 0;
+    n = RxComp(&Regexp);
+    if (n == 0) return 0;
+    n = RxOptimize(n);
+    x = n;
+    while (x->fNext) x = x->fNext;
+    x->fNext = NewNode(RE_END);
+    return n;
+}
+
+void RxFree(RxNode *n) {
+    RxNode *p;
+
+    while (n) {
+        p = n;
+        n = n->fNext;
+        switch (p->fWhat) {
+        case RE_INSET:
+        case RE_NOTINSET:
+        case RE_CHAR:
+            free(p->fChar);
+            break;
+        default:
+            break;
+        }
+        free(p);
+    }
+}
+
+#define ChClass(x) (((((x) >= _T('A')) && ((x) <= _T('Z'))) || (((x) >= _T('a')) && ((x) <= _T('z'))) || (((x) >= _T('0')) && ((x) <= _T('9'))))?1:0)
+
+static RxMatchRes *match;
+static LPCTSTR bop;
+static LPCTSTR eop;
+static int flags = RX_CASE;
+static LPCTSTR rex;
+
+int RxMatch(RxNode *rx) {
+    RxNode *n = rx;
+
+    //_tprintf(_T(">>"));
+    while (n) {
+        //_tprintf(_T("%-50.50s\n", rex));
+        //RxDump(1, n);
+        switch (n->fWhat) {
+        case RE_NOTHING:
+            break;
+        case RE_CASE:
+            flags |= RX_CASE;
+            break;
+        case RE_NCASE:
+            flags &= ~RX_CASE;
+            break;
+        case RE_ATBOL:
+            if (rex != bop) return 0;
+            break;
+        case RE_ATEOL:
+            if (rex != eop) return 0;
+            break;
+        case RE_ANY:
+            if (rex == eop) return 0;
+            rex++;
+            break;
+        case RE_WSPACE:
+            if (rex == eop) return 0;
+            if (*rex != _T(' ') && *rex != _T('\n') && *rex != _T('\r') && *rex != _T('\t')) return 0;
+            rex++;
+            break;
+        case RE_NWSPACE:
+            if (rex == eop) return 0;
+            if (*rex == _T(' ') || *rex == _T('\n') || *rex == _T('\r') || *rex == _T('\t')) return 0;
+            rex++;
+            break;
+        case RE_WORD:
+            if (rex == eop) return 0;
+            if (!_istalnum(*rex)) return 0;
+            rex++;
+            break;
+        case RE_NWORD:
+            if (rex == eop) return 0;
+            if (_istalnum(*rex)) return 0;
+            rex++;
+            break;
+        case RE_DIGIT:
+            if (rex == eop) return 0;
+            if (!_istdigit(*rex)) return 0;
+            rex++;
+            break;
+        case RE_NDIGIT:
+            if (rex == eop) return 0;
+            if (_istdigit(*rex)) return 0;
+            rex++;
+            break;
+        case RE_UPPER:
+            if (rex == eop) return 0;
+            if (!_istupper(*rex)) return 0;
+            rex++;
+            break;
+        case RE_LOWER:
+            if (rex == eop) return 0;
+            if (!_istlower(*rex)) return 0;
+            rex++;
+            break;
+        case RE_ATBOW:
+            if (rex >= eop) return 0;
+            if (rex > bop) {
+                if ((ChClass(*rex) != 1) || (ChClass(*(rex-1)) != 0)) return 0;
+            }
+            break;
+        case RE_ATEOW:
+            if (rex <= bop) return 0;
+            if (rex < eop) {
+                if ((ChClass(*rex) != 0) || (ChClass(*(rex-1)) != 1)) return 0;
+            }
+            break;
+        case RE_CHAR:
+            if (rex == eop) return 0;
+            if (flags & RX_CASE) {
+                if (*n->fChar != *rex) return 0;
+                if (memcmp(rex, n->fChar, n->fLen) != 0) return 0;
+            } else {
+                for (int i = 0; i < n->fLen; i++)
+                    if (_totupper(rex[i]) != _totupper(n->fChar[i]))
+                        return 0;
+            }
+            rex += n->fLen;
+            break;
+        case RE_INSET:
+            if (rex == eop) return 0;
+#ifdef _UNICODE
+            if ((n->fChar[(TCHAR)(*rex) >> 3] & (1 << ((TCHAR)(*rex) & 7))) == 0) return 0;
+#else // _UNICODE
+            if ((n->fChar[(unsigned char)(*rex) >> 3] & (1 << ((unsigned char)(*rex) & 7))) == 0) return 0;
+#endif // _UNICODE
+            rex++;
+            break;
+        case RE_NOTINSET:
+            if (rex == eop) return 0;
+#ifdef _UNICODE
+            if (n->fChar[(TCHAR)(*rex) >> 3] & (1 << ((TCHAR)(*rex) & 7))) return 0;
+#else // _UNICODE
+            if (n->fChar[(unsigned char)(*rex) >> 3] & (1 << ((unsigned char)(*rex) & 7))) return 0;
+#endif // _UNICODE
+            rex++;
+            break;
+        case RE_JUMP:
+            n = n->fPtr;
+            continue;
+        case RE_END:
+            return 1;
+        case RE_BREAK:
+            n = n->fNext;
+            if (n->fNext == 0) break;
+            n = n->fNext;
+            if (n->fWhat & RE_BRANCH) {
+                while ((n->fWhat & RE_BRANCH) && n->fPtr && ((n->fWhat & 0xFF) == _T('|')))
+                    n = n->fPtr->fNext;
+            }
+            if (n->fWhat & RE_GROUP) {
+                int C = 1;
+                n = n->fNext;
+                while ((C > 0) && n) {
+                    if (n->fWhat & RE_GROUP) {
+                        if (n->fWhat & RE_OPEN) C++;
+                        else C--;
+                    }
+                    if (C == 0) break;
+                    n = n->fNext;
+                }
+            }
+            break;
+        default:
+            if (n->fWhat & RE_GROUP) {
+                if (n->fWhat & RE_MEM) {
+                    LPCTSTR save = rex;
+                    int b = n->fWhat & 0xFF;
+                    int fl = flags;
+
+                    if (RxMatch(n->fNext) == 0) {
+                        flags = fl;
+                        if (n->fWhat & RE_OPEN)
+                            match->Open[b] = -1;
+                        else
+                            match->Close[b] = -1;
+                        return 0;
+                    }
+
+                    if (n->fWhat & RE_OPEN) {
+                        //                        if (match->Open[b] == -1)
+                        match->Open[b] = (int) (save - bop);
+                    } else {
+                        //                        if (match->Close[b] == -1)
+                        match->Close[b] = (int) (save - bop);
+                    }
+                    return 1;
+                }
+            } else if (n->fWhat & RE_BRANCH) {
+                LPCTSTR save = rex;
+                int fl = flags;
+
+                if ((n->fWhat & RE_GREEDY) == 0) {
+                    if (RxMatch(n->fPtr) == 1) return 1;
+                    flags = fl;
+                    rex = save;
+                } else {
+                    if (RxMatch(n->fNext) == 1) return 1;
+                    flags = fl;
+                    rex = save;
+                    n = n->fPtr;
+                    continue;
+                }
+            }
+            break;
+        }
+        n = n->fNext;
+    }
+    /* NOTREACHED */
+    assert(1 == 0 /* internal regexp error */);
+    return 0;
+}
+
+int RxTry(RxNode *rx, LPCTSTR s) {
+    int fl = flags;
+    rex = s;
+    for (int i = 0; i < NSEXPS; i++)
+        match->Open[i] = match->Close[i] = -1;
+    if (RxMatch(rx)) {
+        match->Open[0] = (int) (s - bop);
+        match->Close[0] = (int) (rex - bop);
+        return 1;
+    }
+    flags = fl;
+    return 0;
+}
+
+int RxExec(RxNode *Regexp, LPCTSTR Data, int Len, LPCTSTR Start, RxMatchRes *Match, unsigned int RxOpt) {
+    TCHAR Ch;
+    if (Regexp == 0) return 0;
+
+    match = Match;
+    bop = Data;
+    eop = Data + Len;
+
+    flags = RxOpt;
+
+    for (int i = 0; i < NSEXPS; i++) Match->Open[i] = Match->Close[i] = -1;
+
+    switch (Regexp->fWhat) { // this should be more clever
+    case RE_ATBOL:     // match is anchored
+        return RxTry(Regexp, Start);
+    case RE_CHAR:    // search for a character to match
+        Ch = Regexp->fChar[0];
+        if (Start == eop)
+            break;
+        if (flags & RX_CASE) {
+            while (1) {
+                while (Start < eop && *Start != Ch)
+                    Start++;
+                if (Start == eop)
+                    break;
+                if (RxTry(Regexp, Start))
+                    return 1;
+                if (++Start == eop)
+                    break;
+            }
+        } else {
+            Ch = (TCHAR)_totupper(Ch);
+            while (1) {
+                while (Start < eop && (TCHAR) _totupper(*Start) != Ch)
+                    Start++;
+                if (Start == eop)
+                    break;
+                if (RxTry(Regexp, Start))
+                    return 1;
+                if (++Start == eop)
+                    break;
+            }
+        }
+        break;
+    default:         // (slow)
+        do {
+            if (RxTry(Regexp, Start)) return 1;
+        } while (Start++ < eop);
+        break;
+    }
+    return 0;
+}
+
+#define FLAG_UP_CASE     1
+#define FLAG_DOWN_CASE   2
+#define FLAG_UP_NEXT     4
+#define FLAG_DOWN_NEXT   8
+
+static int add(int *len, LPTSTR *s, LPCTSTR a, int alen, int &flag) {
+    int NewLen = *len + alen;
+    int i;
+
+    NewLen = NewLen * 2;
+
+    if (alen == 0)
+        return 0;
+
+    if (*s) {
+        *s = (LPTSTR) realloc(*s, NewLen);
+        assert(*s);
+        memcpy(*s + *len, a, alen);
+    } else {
+        *s = (LPTSTR) malloc(NewLen);
+        assert(*s);
+        memcpy(*s, a, alen);
+        *len = 0;
+    }
+    if (flag & FLAG_UP_CASE) {
+        LPTSTR p = *s + *len;
+
+        for (i = 0; i < alen; i++) {
+            *p = (TCHAR)_totupper(*p);
+            p++;
+        }
+    } else if (flag & FLAG_DOWN_CASE) {
+        LPTSTR p = *s + *len;
+
+        for (i = 0; i < alen; i++) {
+            *p = (TCHAR)_totlower(*p);
+            p++;
+        }
+    }
+    if (flag & FLAG_UP_NEXT) {
+        LPTSTR p = *s + *len;
+
+        *p = (TCHAR)_totupper(*p);
+        flag &= ~FLAG_UP_NEXT;
+    } else if (flag & FLAG_DOWN_NEXT) {
+        LPTSTR p = *s + *len;
+
+        *p = (TCHAR)_totlower(*p);
+        flag &= ~FLAG_DOWN_NEXT;
+    }
+    *len += alen;
+    return 0;
+}
+
+int RxReplace(LPCTSTR rep, LPCTSTR Src, int /*len*/, RxMatchRes match, LPTSTR *Dest, int *Dlen) {
+    int dlen = 0;
+    LPTSTR dest = 0;
+    TCHAR Ch;
+    int n;
+    int flag = 0;
+
+    *Dest = 0;
+    *Dlen = 0;
+    //    add(&dlen, &dest, Src, match.Open[0]);
+    while (*rep) {
+        switch (Ch = *rep++) {
+            //        case _T('&'):
+            //            add(&dlen, &dest, Src + match.Open[0], match.Close[0] - match.Open[0], flag);
+            //            break;
+        case _T('\\'):
+            switch (Ch = *rep++) {
+            case _T('0'):
+            case _T('1'): case _T('2'): case _T('3'):
+            case _T('4'): case _T('5'): case _T('6'):
+            case _T('7'): case _T('8'): case _T('9'):
+                n = Ch - 48;
+
+                if (match.Open[n] != -1 && match.Close[n] != -1) {
+                    add(&dlen, &dest, Src + match.Open[n], match.Close[n] - match.Open[n], flag);
+                } else return -1;
+                break;
+            case 0:
+                if (dest) free(dest);
+                return -1; // error
+            case _T('r'): Ch = _T('\r'); add(&dlen, &dest, &Ch, 1, flag); break;
+            case _T('n'): Ch = _T('\n'); add(&dlen, &dest, &Ch, 1, flag); break;
+            case _T('b'): Ch = _T('\b'); add(&dlen, &dest, &Ch, 1, flag); break;
+            case _T('a'): Ch = _T('\a'); add(&dlen, &dest, &Ch, 1, flag); break;
+            case _T('t'): Ch = _T('\t'); add(&dlen, &dest, &Ch, 1, flag); break;
+            case _T('U'): flag |= FLAG_UP_CASE; break;
+            case _T('u'): flag |= FLAG_UP_NEXT; break;
+            case _T('L'): flag |= FLAG_DOWN_CASE; break;
+            case _T('l'): flag |= FLAG_DOWN_NEXT; break;
+            case _T('E'):
+            case _T('e'): flag &= ~(FLAG_UP_CASE | FLAG_DOWN_CASE); break;
+            case _T('x'):
+                {
+                    int N = 0;
+                    int A = 0;
+
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
+                    rep++;
+                    A = N << 4;
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 9) N = N + 48 - 65 + 10; if (N > 15) return 0;
+                    rep++;
+                    A = A + N;
+                    Ch = (TCHAR)A;
+                }
+                add(&dlen, &dest, &Ch, 1, flag);
+                break;
+            case _T('d'):
+                {
+                    int N = 0;
+                    int A = 0;
+
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 9) return 0;
+                    rep++;
+                    A = N * 100;
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 9) return 0;
+                    rep++;
+                    A = N * 10;
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 9) return 0;
+                    rep++;
+                    A = A + N;
+                    Ch = (TCHAR)A;
+                }
+                add(&dlen, &dest, &Ch, 1, flag);
+                break;
+            case _T('o'):
+                {
+                    int N = 0;
+                    int A = 0;
+
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 7) return 0;
+                    rep++;
+                    A = N * 64;
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 7) return 0;
+                    rep++;
+                    A = N * 8;
+                    if (*rep == 0) return 0;
+                    N = _totupper(*rep) - 48; if (N > 7) return 0;
+                    rep++;
+                    A = A + N;
+                    Ch = (TCHAR)A;
+                }
+                add(&dlen, &dest, &Ch, 1, flag);
+                break;
+            default:
+                add(&dlen, &dest, &Ch, 1, flag);
+                break;
+            }
+            break;
+        default:
+            add(&dlen, &dest, &Ch, 1, flag);
+            break;
+        }
+    }
+    //    add(&dlen, &dest, Src + match.Close[0], len - match.Close[0]);
+    *Dlen = dlen;
+    *Dest = dest;
+    return 0;
+}
+
+#if 0
+
+static void RxDump(int N, RxNode *n) {
+    while (n) {
+        for (int i = 0; i < N; i++) _tprintf(_T("    "));
+        switch (n->fWhat) {
+        case RE_NOTHING:   _tprintf(_T("NOTHING\n")); break;
+        case RE_CHAR:      _tprintf(_T("CHAR '%.1s'\n"), n->fChar); break;
+        case RE_ATBOL:     _tprintf(_T("^\n")); break;
+        case RE_ATEOL:     _tprintf(_T("$\n")); break;
+        case RE_ANY:       _tprintf(_T(".\n")); break;
+        case RE_INSET:     _tprintf(_T("[\n")/*, n->fChar*/); break;
+        case RE_NOTINSET:  _tprintf(_T("[^\n")/*, n->fChar*/); break;
+        case RE_ATBOW:     _tprintf(_T("<\n")); break;
+        case RE_ATEOW:     _tprintf(_T(">\n")); break;
+        case RE_WSPACE:    _tprintf(_T("WSPACE\n")); break;
+        case RE_NWSPACE:   _tprintf(_T("NWSPACE\n")); break;
+        case RE_UPPER:     _tprintf(_T("UPPER\n")); break;
+        case RE_LOWER:     _tprintf(_T("LOWER\n")); break;
+        case RE_JUMP:      _tprintf(_T("JUMP\n")); break;
+        case RE_BREAK:     _tprintf(_T("BREAK\n")); break;
+        case RE_END:       _tprintf(_T("END\n")); break;
+        default:
+            if (n->fWhat & RE_GROUP) {
+                if (n->fWhat & RE_MEM) {
+                    if (n->fWhat & RE_OPEN)  _tprintf(_T("(  %d\n"), n->fWhat & 0xFF);
+                    if (n->fWhat & RE_CLOSE) _tprintf(_T(")  %d\n"), n->fWhat & 0xFF);
+                } else {
+                    if (n->fWhat & RE_OPEN)  _tprintf(_T("{\n"));
+                    if (n->fWhat & RE_CLOSE) _tprintf(_T("}\n"));
+                }
+            } else if (n->fWhat & RE_BRANCH) {
+                if (n->fWhat & RE_GREEDY) {
+                    _tprintf(_T("%c\n"), n->fWhat & 0xFF);
+                } else {
+                    _tprintf(_T("%c\n"), n->fWhat & 0xFF);
+                }
+            } else {
+                _tprintf(_T("???????????????\n"));
+            }
+            break;
+        }
+        n = n->fNext;
+    }
+}
+
+#define TEST(rc,rx,st) \
+    _tcscpy(line,st); \
+    assert((a = RxCompile(rx)) != 0); \
+    puts(_T("\n--- " rx " -- " st " -- ")); \
+    RxDump(0,a);\
+    assert(rc == RxExec(a, line, _tcslen(line), line, &b)); \
+    RxFree(a);
+
+int main() {
+    RxNode *a;
+    RxMatchRes b;
+    TCHAR line[1024];
+
+    TEST(1, _T("a"), _T("a"));
+    TEST(0, _T("b"), _T("a"));
+    TEST(1, _T("aaaa"), _T("aaaa"));
+    TEST(0, _T("bbbb"), _T("aaaa"));
+    TEST(1, _T("."), _T("a"));
+    TEST(0, _T("."), _T(""));
+    TEST(1, _T("a.."), _T("axx"));
+    TEST(0, _T("a.."), _T("b.."));
+    TEST(1, _T("a?b"), _T("ab"));
+    TEST(1, _T("a?b"), _T("xb"));
+    TEST(0, _T("a?C"), _T("xb"));
+    TEST(1, _T("{aa}?b"), _T("aab"));
+    TEST(1, _T("{aa}?b"), _T("xab"));
+    TEST(0, _T("{aa}?C"), _T("xxb"));
+    TEST(1, _T("^aa"), _T("aa"));
+    TEST(0, _T("^aa"), _T("baa"));
+    TEST(1, _T("^aa$"),_T("aa"));
+    TEST(0, _T("^aa$"), _T("baab"));
+    TEST(1, _T("a*b"), _T("aaab"));
+    TEST(0, _T("a*b"), _T("aaaa"));
+    TEST(1, _T("{aa}*b"), _T("aaab"));
+    TEST(0, _T("{aa}*b"), _T("aaaa"));
+    TEST(1, _T("b+"), _T("bb"));
+    TEST(1, _T("b+"), _T("b"));
+    TEST(0, _T("b+"), _T("a"));
+    TEST(1, _T("^b+$"), _T("b"));
+    TEST(0, _T("^b+$"), _T("aba"));
+    TEST(1, _T("a|b"), _T(" a"));
+    TEST(1, _T("a|b"), _T(" b"));
+    TEST(0, _T("a|b"), _T(" c"));
+    TEST(1, _T("a|b|c|d|e"), _T(" a "));
+    TEST(1, _T("a|b|c|d|e"), _T(" c "));
+    TEST(1, _T("a|b|c|d|e"), _T(" e "));
+    TEST(0, _T("a|b|c|d|e"), _T(" x "));
+    TEST(1, _T("{a}|{b}|{c}|{d}|{e}"), _T(" a "));
+    TEST(1, _T("{a}|{b}|{c}|{d}|{e}"), _T(" c "));
+    TEST(1, _T("{a}|{b}|{c}|{d}|{e}"), _T(" e "));
+    TEST(0, _T("{a}|{b}|{c}|{d}|{e}"), _T(" x "));
+    TEST(1, _T("^xx{alpha}|{beta}xx$"), _T("xxalphaxx"));
+    TEST(1, _T("^xx{alpha}|{beta}xx$"), _T("xxbetaxx"));
+    TEST(1, _T("[a-z]"), _T("aaa"));
+    TEST(1, _T("^{Error}|{Warning}"), _T("Warning search.cpp 35: Conversion may lose significant digits in function AskReplace()"));
+    TEST(1, _T("^{Error}|{Warning} (.+)"), _T("Warning search.cpp 35: Conversion may lose significant digits in function AskReplace()"));
+    TEST(1, _T("^{Error}|{Warning} ([a-z.]#) ([0-9]#)"), _T("Warning search.cpp 35: Conversion may lose significant digits in function AskReplace()"));
+    TEST(1, _T("^{Error}|{Warning} (.+) ([0-9]+): (.*)$"), _T("Warning search.cpp 35: Conversion may lose significant digits in function AskReplace()"));
+    TEST(1, _T("^{Error}|{Warning} (.+) ([0-9]+): (.*)$"), _T("Error search.cpp 35: Conversion may lose significant digits in function AskReplace()"));
+    TEST(1, _T("^([a-z]+ +)*\\("), _T("blabla bla bla bla ("));
+    TEST(1, _T("^([a-z]+\\s+)+\\("), _T("blabla bla bla bla ("));
+    TEST(1, _T("^([a-z]+\\s*)+\\("), _T("blabla bla bla bla("));
+    TEST(1, _T("^([a-z]+\\s+)+\\("), _T("blabla bla   bla bla ("));
+    TEST(1, _T("^([a-z]+\\s*)+\\("), _T("blabla   bla bla bla("));
+    TEST(1, _T("^([a-z]# #)*\\("), _T("blabla bla bla bla ("));
+    TEST(1, _T("^([a-z]+ @)@\\("), _T("blabla bla bla bla ("));
+    TEST(1, _T("^[\\x20-\\xFF]+$"), _T("blabla"));
+    TEST(1, _T("{a{a{a{a|a}|{a|a}a}a}a|a}"), _T("aaaaaaaaaaaaaaaaa"));
+
+    while (1) {
+        _tprintf(_T ("Regexp: ")); fflush(stdout); gets(line);
+        if (!*line) break;
+        a = RxCompile(line); RxDump(0, a);
+        _tprintf(_T ("String: ")); fflush(stdout); gets(line);
+        _tprintf(_T ("rc = %d\n"), RxExec(a, line, _tcslen(line), line, &b));
+        for (int i = 0; i < NSEXPS; i++) {
+            if (b.Open[i] != -1) {
+                _tprintf(_T ("%d: %d %d\n"), i, b.Open[i], b.Close[i]);
+            }
+        }
+        RxFree(a);
+    }
+    return 0;
+}
+
+#endif
diff --git a/Src/editlib/cregexp.h b/Src/editlib/cregexp.h
new file mode 100644 (file)
index 0000000..1d7f9e5
--- /dev/null
@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    regexp.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Marko Macek
+//  E-mail:     Marko.Macek@gmx.net or mark@hermes.si
+//
+//  Some handy stuff to deal with regular expressions
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __REGEX_H
+#define __REGEX_H
+
+/*
+ * Operator:
+ *
+ * ^            Match the beginning of line
+ * $            Match the end of line
+ * .            Match any character
+ * [ ]          Match characters in set
+ * [^ ]         Match characters not in set
+ * ?            Match previous pattern 0 or 1 times (greedy)
+ * |            Match previous or next pattern
+ * @            Match previous pattern 0 or more times (non-greedy)
+ * #            Match previous pattern 1 or more times (non-greedy)
+ * *            Match previous pattern 0 or more times (greedy)
+ * +            Match previous pattern 1 or more times (greedy)
+ * { }          Group characters to form one pattern
+ * ( )          Group and remember
+ * \            Quote next character (only of not a-z)
+ * <            Match beginning of a word
+ * >            Match end of a word
+ * \x##         Match character with ASCII code ## (hex)
+ * \N###        Match ascii code ### (dec)
+ * \o###        Match ascii code
+ * \a           Match \a              \r           Match 0x13 (cr)
+ * \b           Match \b              \t           Match 0x09 (tab)
+ * \f           Match \f              \v           Match \v
+ * \n           Match 0x10 (lf)       \e           Match escape (^E)
+ * \s           Match whitespace (cr/lf/tab/space)
+ * \S           Match nonwhitespace (!\S)
+ * \w           Match word character
+ * \W           Match non-word character
+ * \d           Match digit character
+ * \D           Match non-digit character
+ * \U           Match uppercase
+ * \L           Match lowercase
+ * \C           Match case sensitively from here on
+ * \c           Match case ingnore from here on
+ */
+
+#define RE_NOTHING         0  // nothing
+#define RE_JUMP            1  // jump to
+#define RE_BREAK           2  // break |
+#define RE_ATBOL           3  // match at beginning of line
+#define RE_ATEOL           4  // match at end of line
+#define RE_ATBOW           5  // match beginning of word
+#define RE_ATEOW           6  // match end of word
+#define RE_CASE            7  // match case sensitively from here
+#define RE_NCASE           8  // ignore case from here.
+#define RE_END            31  // end of regexp
+
+#define RE_ANY      (32 +  1) // match any character
+#define RE_INSET    (32 +  2) // match if in set
+#define RE_NOTINSET (32 +  3) // match if not in set
+#define RE_CHAR     (32 +  4) // match character string
+#define RE_WSPACE   (32 +  5) // match whitespace
+#define RE_NWSPACE  (32 +  6) // match whitespace
+#define RE_UPPER    (32 +  7) // match uppercase
+#define RE_LOWER    (32 +  8) // match lowercase
+#define RE_DIGIT    (32 +  9) // match digit
+#define RE_NDIGIT   (32 + 10) // match non-digit
+#define RE_WORD     (32 + 11) // match word
+#define RE_NWORD    (32 + 12) // match non-word
+
+#define RE_GROUP         256  // grouping
+#define RE_OPEN          512  // open (
+#define RE_CLOSE        1024  // close )
+#define RE_MEM          2048  // store () match
+
+#define RE_BRANCH       4096
+#define RE_GREEDY       2048  // do a greedy match (as much as possible)
+
+#define NSEXPS            64  // for replace only 0-9
+
+#define RX_CASE         1  // matchcase
+
+typedef struct _RxNode RxNode;
+
+struct _RxNode {
+    short fWhat;
+    short fLen;
+    RxNode *fPrev;
+    RxNode *fNext;
+    union {
+        LPTSTR fChar;
+        RxNode *fPtr;
+    };
+};
+
+typedef struct {
+    int Open[NSEXPS];    // -1 = not matched
+    int Close[NSEXPS];
+} RxMatchRes;
+
+RxNode EDITPADC_CLASS *RxCompile(LPCTSTR Regexp);
+int EDITPADC_CLASS RxExec(RxNode *Regexp, LPCTSTR Data, int Len, LPCTSTR Start, RxMatchRes *Match, unsigned int RxOpt = RX_CASE);
+int EDITPADC_CLASS RxReplace(LPCTSTR rep, LPCTSTR Src, int len, RxMatchRes match, LPTSTR *Dest, int *Dlen);
+void EDITPADC_CLASS RxFree(RxNode *Node);
+
+#endif
diff --git a/Src/editlib/crystaleditviewex.cpp b/Src/editlib/crystaleditviewex.cpp
new file mode 100644 (file)
index 0000000..0e43071
--- /dev/null
@@ -0,0 +1,72 @@
+// CrystalEditViewEx.cpp: Implementierung der Klasse CCrystalEditViewEx.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "CrystalParser.h"
+#include "CrystalEditViewEx.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Konstruktion/Destruktion
+//////////////////////////////////////////////////////////////////////
+IMPLEMENT_DYNCREATE(CCrystalEditViewEx,CCrystalEditView)
+
+
+CCrystalEditViewEx::CCrystalEditViewEx()
+: CCrystalEditView()
+{
+       m_pSyntaxParser = NULL;
+}
+
+
+HINSTANCE CCrystalEditViewEx::GetResourceHandle()
+{
+#ifdef CE_DLL_BUILD
+       return g_hDllInstance;
+#else
+       // -> HE
+       // call inherited
+       return CCrystalEditView::GetResourceHandle();
+       // <- HE
+       // OLD
+       //return AfxGetInstanceHandle();
+#endif
+}
+
+
+DWORD CCrystalEditViewEx::ParseLine( DWORD dwCookie, int nLineIndex, 
+                                                                                                                                               TEXTBLOCK *pBuf, int &nActualItems )
+{
+       if( m_pSyntaxParser )
+       {
+               CCrystalTextBlock       *pTextBlock = 
+                       pBuf? new CCrystalTextBlock( (CCrystalTextBlock::TEXTBLOCK*)pBuf, nActualItems ) : NULL;
+               dwCookie = m_pSyntaxParser->ParseLine( dwCookie, nLineIndex, pTextBlock );
+               
+               if( pTextBlock )
+                       delete pTextBlock;
+
+               return dwCookie;
+       }
+       else
+               return 0;
+}
+
+
+CCrystalParser *CCrystalEditViewEx::SetSyntaxParser( CCrystalParser *pParser )
+{
+       CCrystalParser  *pOldParser = m_pSyntaxParser;
+
+       m_pSyntaxParser = pParser;
+
+       if( pParser )
+  //BEGIN FP
+    pParser->m_pTextView = this;
+               /*ORIGINAL
+    pParser->m_pEditViewEx = this;
+               */
+  //END FP
+
+       return pOldParser;
+}
diff --git a/Src/editlib/crystaleditviewex.h b/Src/editlib/crystaleditviewex.h
new file mode 100644 (file)
index 0000000..ed23e92
--- /dev/null
@@ -0,0 +1,97 @@
+// CrystalEditViewEx.h: Schnittstelle für die Klasse CCrystalEditViewEx.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CRYSTALEDITVIEWEX_H__5353A214_1059_11D3_929E_CEFE4CA77E5E__INCLUDED_)
+#define AFX_CRYSTALEDITVIEWEX_H__5353A214_1059_11D3_929E_CEFE4CA77E5E__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ccrystaleditview.h"
+
+#ifndef __CRYSTALSYNTAXPARSER_H__
+#include "CrystalParser.h"
+#endif
+
+
+class EDITPADC_CLASS CCrystalEditViewEx : public CCrystalEditView  
+{
+       DECLARE_DYNCREATE(CCrystalEditViewEx)
+
+protected:
+       friend class CCrystalParser;
+
+/** @construction/destruction */
+public:
+       CCrystalEditViewEx();
+
+/** @operations */
+public:
+       /**
+       Attaches a syntax parser to this view.
+
+       @param pParser
+               The syntax parser to attach to this view. The Parser must be derived
+               from CCrystalParser.
+
+       @return
+               The syntax parser that was used until the call to this function or
+               NULL if no one was attached to this view.
+       */
+       CCrystalParser *SetSyntaxParser( CCrystalParser *pParser );
+
+/** @overridables */
+protected:
+       /**
+       @description
+               Returns a handle to the instance (DLL or EXE)
+
+       @return
+               Handle to the Instance (DLL or EXE)
+
+       @remark
+               Equivalent to AfxGetInstanceHandle()
+       */
+       virtual HINSTANCE GetResourceHandle();
+
+       
+       /**
+       @description
+               Is called by tht view, when there is a Line to parse.
+
+       @param dwCookie
+               The result of parsing the previous line. This parameter contains flags,
+               you set while parsing the previous line. Normaly this will be flags that
+               indicate a region that was still open at the end of the last line. You
+               set those flags for a line by returning them ored (|).
+       @param nLineIndex
+               The zero-based index of the line to parse.
+       @param pBuf
+               You have to split the lines in to parts which are specified by there
+               beginning (zero-based index of the character in this line) and there text
+               color. You have to specifie each one of this blocks in this Buffer.
+               You can define a new Block with the macro DEFINE_BLOCK( pos, colorindex ).
+
+               When the function ist called with this parameter set zu NULL, you only
+               have to calculate the cookies.
+       @param nActualItems
+               Used by the macro DEFINE_BLOCK.
+
+       @return 
+               The calculated flags for this line (see dwCookie).
+       */
+       virtual DWORD ParseLine( DWORD dwCookie, int nLineIndex, 
+               TEXTBLOCK *pBuf, int &nActualItems );
+       
+/** @attributes */
+protected:
+       /**
+       @description
+               The parser used to parse the Text or NULL if no parser is used.
+       */
+       CCrystalParser *m_pSyntaxParser;
+};
+
+#endif // !defined(AFX_CRYSTALEDITVIEWEX_H__5353A214_1059_11D3_929E_CEFE4CA77E5E__INCLUDED_)
diff --git a/Src/editlib/crystalparser.cpp b/Src/editlib/crystalparser.cpp
new file mode 100644 (file)
index 0000000..ae4c1f3
--- /dev/null
@@ -0,0 +1,108 @@
+////////////////////////////////////////////////////////////////////////////
+//     File:           CrystalParser.cpp
+//
+//     Author:         Sven Wiegand
+//     E-mail:         sven.wiegand@gmx.de
+//
+//     Implementation of the CCrystalParser class, a part of Crystal Edit -
+//     syntax coloring text editor.
+//
+//     You are free to use or modify this code to the following restrictions:
+//     - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//     will be enough. If you can't (or don't want to), contact me personally.
+//     - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "CrystalParser.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+IMPLEMENT_DYNAMIC( CCrystalParser, CObject )
+
+CCrystalParser::CCrystalParser()
+{
+       m_pTextView = NULL;
+}
+
+
+CCrystalParser::~CCrystalParser()
+{
+}
+
+
+DWORD CCrystalParser::ParseLine(DWORD /*dwCookie*/, 
+                                                               int /*nLineIndex*/, 
+                                                               CCrystalTextBlock * /*pBlock*/ )
+{
+       return 0;
+}
+
+
+void CCrystalParser::WrapLine( int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks )
+{
+       // The parser must be attached to a view!
+       ASSERT( m_pTextView );
+
+       int                     nLineLength = m_pTextView->GetLineLength( nLineIndex );
+       int                     nTabWidth = m_pTextView->GetTabSize();
+       int                     nLineCharCount = 0;
+       int                     nCharCount = 0;
+       LPCTSTR szLine = m_pTextView->GetLineChars( nLineIndex );
+       int                     nLastBreakPos = 0;
+       int                     nLastCharBreakPos = 0;
+       BOOL            bWhitespace = FALSE;
+
+       for( int i = 0; i < nLineLength; i++ )
+       {
+               // remember position of whitespace for wrap
+               if( bWhitespace )
+               {
+                       nLastBreakPos = i;
+                       nLastCharBreakPos = nCharCount;
+                       bWhitespace = FALSE;
+               }
+
+               // increment char counter (evtl. expand tab)
+               if( szLine[i] == _T('\t') )
+               {
+                       nLineCharCount+= (nTabWidth - nCharCount % nTabWidth);
+                       nCharCount+= (nTabWidth - nCharCount % nTabWidth);
+               }
+               else
+               {
+                       nLineCharCount++;
+                       nCharCount++;
+               }
+
+               // remember whitespace
+               if( szLine[i] == _T('\t') || szLine[i] == _T(' ') )
+                       bWhitespace = TRUE;
+
+               // wrap line
+               if( nLineCharCount >= nMaxLineWidth )
+               {
+                       if( anBreaks )
+                       {
+                               // if no wrap position found, but line is to wide, 
+                               // wrap at current position
+                               if( (nBreaks && nLastBreakPos == anBreaks[nBreaks - 1]) || (!nBreaks && !nLastBreakPos) )
+                               {
+                                       nLastBreakPos = i;
+                                       nLastCharBreakPos = nCharCount;
+                               }
+
+                               anBreaks[nBreaks++] = nLastBreakPos;
+                       }
+                       else
+                               nBreaks++;
+
+                       nLineCharCount = nCharCount - nLastCharBreakPos;
+               }
+       }
+}
diff --git a/Src/editlib/crystalparser.h b/Src/editlib/crystalparser.h
new file mode 100644 (file)
index 0000000..b6780d4
--- /dev/null
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////
+//     File:           CrystalParser.h
+//
+//     Author:         Sven Wiegand
+//     E-mail:         sven.wiegand@gmx.de
+//
+//     Interface of the CCrystalParser class, a part of Crystal Edit -
+//     syntax coloring text editor.
+//
+//     You are free to use or modify this code to the following restrictions:
+//     - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//     will be enough. If you can't (or don't want to), contact me personally.
+//     - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CRYSTALPARSER_H__17435DA0_1F72_11D3_929E_FD90DABF8479__INCLUDED_)
+#define AFX_CRYSTALPARSER_H__17435DA0_1F72_11D3_929E_FD90DABF8479__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "CrystalTextBlock.h"
+
+/**
+Objects of this class are used to describe language properties. At this time
+language properties are:
+<ul>
+       <li> Syntax highlighting (method ParseLine())
+       <li> Word wrapping (method WrapLine())
+</ul>
+
+Derive your own class from CCrystalParser and override the method ParseLine()
+to modify syntax highlighting and/or WrapLine() to modify line wrapping.
+
+Use the CCrystalTextView::SetParser() function to attach a parser to a text
+view.
+
+@author Sven Wiegand
+*/
+class EDITPADC_CLASS CCrystalParser : public CObject  
+{
+       DECLARE_DYNAMIC(CCrystalParser)
+       friend class CCrystalTextView;
+       friend class CCrystalEditViewEx;
+
+// construction/destruction
+public:
+       CCrystalParser();
+       virtual ~CCrystalParser();
+
+// overridables
+public:
+       /**
+       Is called by tht view, when there is a Line to parse.
+
+       @param dwCookie The result of parsing the previous line. This parameter contains flags,
+               you set while parsing the previous line. Normaly this will be flags that
+               indicate a region that was still open at the end of the last line. You
+               set those flags for a line by returning them ored (|).
+       @param nLineIndex The zero-based index of the line to parse.
+       @param pBlock You have to split the lines in to parts which are specified by there
+               beginning (zero-based index of the character in this line) and there text
+               color. You have to specifie each one of this blocks by adding them to
+               this block array, using CTextBlock::Add(). You do not have to care about
+               the sort to add the elements.
+
+               When the function ist called with this parameter set zu NULL, you only
+               have to calculate the cookies which can be (hoply) done much more faster.
+
+       @return The calculated flags for this line (see dwCookie).
+       */
+       virtual DWORD ParseLine( DWORD dwCookie, int nLineIndex, CCrystalTextBlock *pBlock );
+
+       /**
+       Called by CCrystalTextView-object to wrap the line with the given index into sublines.
+
+       The standard implementation wraps the line behind the first whitespace in front
+       of the word that exceeds the visible line width (nMaxLineWidth). Override
+       this function to provide your own word wrapping.
+
+       <b>Attention:</b> Never call this function directly in other parts of the code
+       call WrapLineCached() instead, which will work much faster in most cases.
+
+       @param nLineIndex The index of the line to wrap
+
+       @param nMaxLineWidth The number of characters a subline of this line should
+       not exceed
+
+       @param anBreaks An array of integers. Put the positions where to wrap the line
+       in that array (its allready allocated). If this pointer is NULL, the function
+       has only to compute the number of breaks (the parameter nBreaks).
+
+       @param nBreaks The number of breaks this line has (number of sublines - 1). When
+       the function is called, this variable is 0. If the line is not wrapped, this value
+       should be 0 after the call.
+
+       @see WrapLineCached()
+       */
+       virtual void WrapLine( int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks );
+
+// attributes
+protected:
+       /**     The text view this parser is attached to. */
+       CCrystalTextView *m_pTextView;
+
+};
+
+#endif // !defined(AFX_CRYSTALPARSER_H__17435DA0_1F72_11D3_929E_FD90DABF8479__INCLUDED_)
diff --git a/Src/editlib/crystaltextblock.cpp b/Src/editlib/crystaltextblock.cpp
new file mode 100644 (file)
index 0000000..0a237e0
--- /dev/null
@@ -0,0 +1,66 @@
+////////////////////////////////////////////////////////////////////////////
+//     File:           CrystalTextBlock.cpp
+//
+//     Author:         Sven Wiegand
+//     E-mail:         sven.wiegand@gmx.de
+//
+//     Implementation of the CCrystalTextBufferEx class, a part of Crystal Edit -
+//     syntax coloring text editor.
+//
+//     You are free to use or modify this code to the following restrictions:
+//     - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//     will be enough. If you can't (or don't want to), contact me personally.
+//     - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "CrystalTextBlock.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+CCrystalTextBlock::CCrystalTextBlock( TEXTBLOCK *pTextBlock, int &rnActualItems )
+: m_rnActualItems( rnActualItems )
+{
+       ASSERT( pTextBlock );
+       m_pTextBlock = pTextBlock;
+}
+
+
+BOOL CCrystalTextBlock::Add( int nCharPos, int nColorIndex )
+{
+       // insert new text block sorted by character position
+       for( int i = 0; i < m_rnActualItems && m_pTextBlock[i].m_nCharPos < nCharPos; i++ );
+
+       // insert text block
+       if( i < m_rnActualItems )
+       {
+               // if new character position allready exists, the replace old one
+               if( m_pTextBlock[i].m_nCharPos == nCharPos )
+               {
+                       m_pTextBlock[i].m_nCharPos = nCharPos;
+                       m_pTextBlock[i].m_nColorIndex = nColorIndex;
+               }
+               else
+               {
+                       for( int j = ++m_rnActualItems - 1; j > i; j-- )
+                       {
+                               m_pTextBlock[j].m_nCharPos = m_pTextBlock[j - 1].m_nCharPos;
+                               m_pTextBlock[j].m_nColorIndex = m_pTextBlock[j - 1].m_nColorIndex;
+                       }
+                       m_pTextBlock[i].m_nCharPos = nCharPos;
+                       m_pTextBlock[i].m_nColorIndex = nColorIndex;
+               }
+       }
+       else
+       {
+               // add text block to end of array
+               m_pTextBlock[m_rnActualItems].m_nCharPos = nCharPos;
+               m_pTextBlock[m_rnActualItems++].m_nColorIndex = nColorIndex;
+       }
+
+       return TRUE;
+}
diff --git a/Src/editlib/crystaltextblock.h b/Src/editlib/crystaltextblock.h
new file mode 100644 (file)
index 0000000..f1fa3cc
--- /dev/null
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////
+//     File:           CrystalTextBlock.h
+//
+//     Author:         Sven Wiegand
+//     E-mail:         sven.wiegand@gmx.de
+//
+//     Interface of the CCrystalTextBlock class, a part of Crystal Edit -
+//     syntax coloring text editor.
+//
+//     You are free to use or modify this code to the following restrictions:
+//     - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//     will be enough. If you can't (or don't want to), contact me personally.
+//     - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CRYSTALTEXTBLOCK_H__37ECF0C1_145F_11D3_929E_444553540000__INCLUDED_)
+#define AFX_CRYSTALTEXTBLOCK_H__37ECF0C1_145F_11D3_929E_444553540000__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+/**
+Objects of this class are passed to CCrystalParser::ParseLine() to get the
+positions of color changes in a text line.
+
+You can simply add a color change using the Add()-Method. You do add the
+color changes sorted by position -- the Add()-Method will do this for you.
+
+@author Sven Wiegand
+*/
+class EDITPADC_CLASS CCrystalTextBlock  
+{
+       friend class CCrystalTextView;
+       friend class CCrystalEditViewEx;
+
+protected:
+       struct TEXTBLOCK
+       {
+               int m_nCharPos;
+               int m_nColorIndex;
+       };
+
+// construction/destruction
+protected:
+       CCrystalTextBlock( TEXTBLOCK *pTextBlock, int &rnActualItems );
+
+// operations
+public:
+       /**
+       Adds a text block to the array.
+
+       You do not need to add the text blocks in the order of character position.
+
+       @param nCharPos
+               Character position of the line, where the text block starts.
+       @param nColorIndex
+               Index of the color to use to colorize the text block.
+       */
+       BOOL Add( int nCharPos, int nColorIndex );
+
+// attributes
+protected:
+       /** text block to work on */
+       TEXTBLOCK       *m_pTextBlock;
+
+       /** Index */
+       int &m_rnActualItems;
+};
+
+#endif // !defined(AFX_CRYSTALTEXTBLOCK_H__37ECF0C1_145F_11D3_929E_444553540000__INCLUDED_)
diff --git a/Src/editlib/cs2cs.cpp b/Src/editlib/cs2cs.cpp
new file mode 100644 (file)
index 0000000..98431bb
--- /dev/null
@@ -0,0 +1,248 @@
+/* Ferda Prantl - character coding conversion engine  */
+
+#include "stdafx.h"
+#include "cs2cs.h"
+#include <string.h>
+#include <malloc.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define FD_ENCODING_LBRACKET _T ("<!--")
+#define FD_ENCODING_MARK     _T ("MYCHARSET")
+#define FD_ENCODING_RBRACKET _T ("-->")
+
+#define codes_count 13
+#define chars_all_count 66
+#define chars_alphabet_count 44
+
+type_codes source_codes[] =
+{
+  {_T ("ASCII"), _T ("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x26\x5c\x22\x3c\x3e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")},
+  {_T ("CP1250"), _T ("\xc1\xc8\xcf\xc9\xcc\xcd\xd2\xd3\xd8\x8a\x8d\xda\xd9\xdd\x8e\xbc\xc0\xc5\xd4\xd6\xdc\xc4\xe1\xe8\xef\xe9\xec\xed\xf2\xf3\xf8\x9a\x9d\xfa\xf9\xfd\x9e\xbe\xe0\xe5\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\x74\xa0\x7c\x63\x52\xb0\x2b\xb6\x7\0\0\0\xd7\0\xf7\0")},
+  {_T ("CP1252"), _T ("\xc1\0\0\xc9\0\xcd\0\xd3\0\x8a\0\xda\0\xdd\0\0\0\0\xd4\xd6\xdc\xc4\xe1\0\0\xe9\0\xed\0\xf3\0\x9a\0\xfa\0\xfd\0\0\0\0\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\x74\xa0\x7c\x63\x52\xb0\x2b\xb6\x7\xbc\xbd\xbe\xd7\xd8\xf7\xf8")},
+  {_T ("CP850"), _T ("\xb5\0\0\x90\0\xd6\0\xe0\0\0\0\xe9\0\xed\0\0\0\0\xe2\x99\x9a\x8e\xa0\0\0\x82\0\xa1\0\xa2\0\0\0\xa3\0\xec\0\0\0\0\x93\x94\x81\x84\xe1\0\x26\x5c\x22\x3c\x3e\0\0\0\0\0\xf8\xf1\xf5\xfa\xac\xab\0\x9e\0\xf6\xed")},
+  {_T ("CP852"), _T ("\xb5\xac\xd2\x90\xb7\xd6\xd5\xe0\xfc\xe6\x9b\xe9\xde\xed\xa6\x95\xe8\x91\xe2\x99\x9a\x8e\xa0\x9f\xd4\x82\xd8\xa1\xe5\xa2\xfd\xe7\x9c\xa3\x85\xec\xa7\x96\xea\x92\x93\x94\x81\x84\xe1\xf5\x26\x5c\x22\x3c\x3e\0\0\0\0\0\xf8\0\xf5\0\0\0\0\x9e\0\xf6\0")},
+  {_T ("IBM852"), _T ("\xb5\xab\xd2\x90\xb7\xd6\xd5\xe0\xfd\xe6\x9b\xe9\xde\xed\xa5\x95\xe8\x91\xe2\x99\x9a\x8e\xa0\x9f\xd4\x82\xd8\xa1\xe5\xa2\xfe\xe7\x9c\xa3\x85\xec\xa6\x96\xea\x92\x93\x94\x81\x84\xe1\xf5\x26\x5c\x22\x3c\x3e\0\0\0\0\0\xf8\0\xf5\0\0\0\0\x9e\0\xf6\0")},
+  {_T ("ISO-8859-1"), _T ("\xc1\0\0\xc9\0\xcd\0\xd3\0\0\0\xda\0\xdd\0\0\0\0\xd4\xd6\xdc\xc4\xe1\0\0\xe9\0\xed\0\xf3\0\0\0\xfa\0\xfd\0\0\0\0\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\0\xa0\x7c\x63\x52\xb0\x2b\xb6\x7\xbc\xbd\xbe\xd7\xd8\xf7\xf8")},
+  {_T ("ISO-8859-2"), _T ("\xc1\xc8\xcf\xc9\xcc\xcd\xd2\xd3\xd8\xa9\xab\xda\xd9\xdd\xae\xa5\xc0\xc5\xd4\xd6\xdc\xc4\xe1\xe8\xef\xe9\xec\xed\xf2\xf3\xf8\xb9\xbb\xfa\xf9\xfd\xbe\xb5\xe0\xe5\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\0\xa0\x7c\x63\x52\xb0\x2b\xb6\x7\xbc\xbd\xbe\xd7\xd8\xf7\xf8")},
+  {_T ("KEYBCS2"), _T ("\x8f\x80\x85\x90\x89\x8b\xa5\x95\x9e\x9b\x86\x97\xa6\x9d\x92\x9c\xab\x8a\xa7\x99\x9a\x8e\xa0\x87\x83\x82\x88\xa1\xa4\xa2\xa9\xa8\x9f\xa3\x96\x98\x91\x8c\xaa\x8d\x93\x94\x81\x84\xe1\xad\x26\x5c\x22\x3c\x3e\0\0\0\0\0\xf8\xf1\xf5\xfa\xac\0\0\x9e\0\xf6\0")},
+  {_T ("KOI8-CS"), _T ("\xe1\xe3\xe4\xf7\xe5\xe9\xee\xef\xf2\xf3\xf4\xf5\xea\xf9\xfa\xec\xe6\xeb\xf0\xed\xe8\xf1\xc1\xc3\xc4\xd7\xc5\xc9\xce\xcf\xd2\xd3\xd4\xd5\xca\xd9\xda\xcc\xc6\xcb\xd0\xcd\xc8\xd1\0\0\x26\x5c\x22\x3c\x3e\0\0\0\0\0\xfe\0\0\0\0\0\0\0\0\0\0")},
+  {_T ("MAC"), _T ("\xe7\0\0\x83\0\xea\0\xee\0\0\0\xf2\0\0\0\0\0\0\xef\x85\x86\x80\x87\0\0\x8e\0\x92\0\x97\0\0\0\x9c\0\0\0\0\0\0\x99\x9a\x9f\x8a\xa7\xa4\x26\x5c\x22\x3c\x3e\xaa\xca\0\x63\xa8\xa1\x2b\x7c\0\0\0\0\0\xaf\xd6\xbf")},
+  {_T ("MACCE"), _T ("\xe7\x89\x91\x83\x9d\xea\xc5\xee\xdb\xe1\xe8\xf2\xf1\xf8\xeb\xbb\xd9\xbd\xef\x85\x86\x80\x87\x8b\x93\x8e\x9e\x92\xcb\x97\xde\xe4\xe9\x9c\xf3\xf9\xec\xbc\xda\xbe\x99\x9a\x9f\x8a\xa7\xa4\x26\x5c\x22\x3c\x3e\xaa\xca\0\x63\xa8\xa1\x2b\x7c\0\0\0\0\0\xaf\xd6\xbf")},
+  {_T ("CORK"), _T ("\xc1\x83\x84\xc9\x85\xcd\x8c\xd3\x90\x92\x94\xda\x97\xdd\x9a\x89\x8f\x88\xd4\xd6\xdc\xc4\xe1\xa3\xa4\xe9\xa5\xed\xac\xf3\xb0\xb2\xb4\xfa\xb7\xfd\xba\xa9\xaf\xa8\xf4\xf6\xfc\xe4\0\0\x26\x5c\x22\x3c\x3e\0\0\0\0\0\0\0\0\0\0\0\0\0\xd8\0\xf8")}
+}, destination_codes[] =
+{
+  {_T ("ASCII"), _T ("\x41\x43\x44\x45\x45\x49\x4e\x4f\x52\x53\x54\x55\x55\x59\x5a\x4c\x52\x4c\x4f\x4f\x55\x41\x61\x63\x64\x65\x65\x69\x6e\x6f\x72\x73\x74\x75\x75\x79\x7a\x6c\x72\x6c\x6f\x6f\x75\x61\x73\x53\x26\x5c\x22\x3c\x3e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20")},
+  {_T ("CP1250"), _T ("\xc1\xc8\xcf\xc9\xcc\xcd\xd2\xd3\xd8\x8a\x8d\xda\xd9\xdd\x8e\xbc\xc0\xc5\xd4\xd6\xdc\xc4\xe1\xe8\xef\xe9\xec\xed\xf2\xf3\xf8\x9a\x9d\xfa\xf9\xfd\x9e\xbe\xe0\xe5\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\x99\xa0\xa6\xa9\xae\xb0\xb1\xb6\xb7\x20\x20\x20\xd7\x20\xf7\x20")},
+  {_T ("CP1252"), _T ("\xc1\x43\x44\xc9\x45\xcd\x4e\xd3\x52\x8a\x54\xda\x55\xdd\x5a\x4c\x52\x4c\xd4\xd6\xdc\xc4\xe1\x63\x64\xe9\x65\xed\x6e\xf3\x72\x9a\x74\xfa\x75\xfd\x7a\x6c\x72\x6c\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\x99\xa0\xa6\xa9\xae\xb0\xb1\xb6\xb7\xbc\xbd\xbe\xd7\xd8\xf7\xf8")},
+  {_T ("CP850"), _T ("\xb5\x43\x44\x90\x45\xd6\x4e\xe0\x52\x53\x54\xe9\x55\xed\x5a\x4c\x52\x4c\xe2\x99\x9a\x8e\xa0\x63\x64\x82\x65\xa1\x6e\xa2\x72\x73\x74\xa3\x75\xec\x7a\x6c\x72\x6c\x93\x94\x81\x84\xe1\xf5\x26\x5c\x22\x3c\x3e\x20\x20\x20\x20\x20\xf8\xf1\xf5\xfa\xac\xab\x20\x9e\x20\xf6\xed")},
+  {_T ("CP852"), _T ("\xb5\xac\xd2\x90\xb7\xd6\xd5\xe0\xfc\xe6\x9b\xe9\xde\xed\xa6\x95\xe8\x91\xe2\x99\x9a\x8e\xa0\x9f\xd4\x82\xd8\xa1\xe5\xa2\xfd\xe7\x9c\xa3\x85\xec\xa7\x96\xea\x92\x93\x94\x81\x84\xe1\xf5\x26\x5c\x22\x3c\x3e\x20\x20\x20\x20\x20\xf8\x20\xf5\x20\x20\x20\x20\x9e\x20\xf6\x20")},
+  {_T ("IBM852"), _T ("\xb5\xab\xd2\x90\xb7\xd6\xd5\xe0\xfd\xe6\x9b\xe9\xde\xed\xa5\x95\xe8\x91\xe2\x99\x9a\x8e\xa0\x9f\xd4\x82\xd8\xa1\xe5\xa2\xfe\xe7\x9c\xa3\x85\xec\xa6\x96\xea\x92\x93\x94\x81\x84\xe1\xf5\x26\x5c\x22\x3c\x3e\x20\x20\x20\x20\x20\xf8\x20\xf5\x20\x20\x20\x20\x9e\x20\xf6\x20")},
+  {_T ("ISO-8859-1"), _T ("\xc1\x43\x44\xc9\x45\xcd\x4e\xd3\x52\x53\x54\xda\x55\xdd\x5a\x4c\x52\x4c\xd4\xd6\xdc\xc4\xe1\x63\x64\xe9\x65\xed\x6e\xf3\x72\x73\x74\xfa\x75\xfd\x7a\x6c\x72\x6c\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\x20\xa0\xa6\xa9\xae\xb0\xb1\xb6\xb7\xbc\xbd\xbe\xd7\xd8\xf7\xf8")},
+  {_T ("ISO-8859-2"), _T ("\xc1\xc8\xcf\xc9\xcc\xcd\xd2\xd3\xd8\xa9\xab\xda\xd9\xdd\xae\xa5\xc0\xc5\xd4\xd6\xdc\xc4\xe1\xe8\xef\xe9\xec\xed\xf2\xf3\xf8\xb9\xbb\xfa\xf9\xfd\xbe\xb5\xe0\xe5\xf4\xf6\xfc\xe4\xdf\xa7\x26\x5c\x22\x3c\x3e\x20\xa0\xa6\xa9\xae\xb0\xb1\xb6\xb7\xbc\xbd\xbe\xd7\xd8\xf7\xf8")},
+  {_T ("KEYBCS2"), _T ("\x8f\x80\x85\x90\x89\x8b\xa5\x95\x9e\x9b\x86\x97\xa6\x9d\x92\x9c\xab\x8a\xa7\x99\x9a\x8e\xa0\x87\x83\x82\x88\xa1\xa4\xa2\xa9\xa8\x9f\xa3\x96\x98\x91\x8c\xaa\x8d\x93\x94\x81\x84\xe1\xad\x26\x5c\x22\x3c\x3e\x20\x20\x20\x20\x20\xf8\xf1\xf5\xfa\xac\x20\x20\x9e\x20\xf6\x20")},
+  {_T ("KOI8-CS"), _T ("\xe1\xe3\xe4\xf7\xe5\xe9\xee\xef\xf2\xf3\xf4\xf5\xea\xf9\xfa\xec\xe6\xeb\xf0\xed\xe8\xf1\xc1\xc3\xc4\xd7\xc5\xc9\xce\xcf\xd2\xd3\xd4\xd5\xca\xd9\xda\xcc\xc6\xcb\xd0\xcd\xc8\xd1\x73\x53\x26\x5c\x22\x3c\x3e\x20\x20\x20\x20\x20\xfe\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20")},
+  {_T ("MAC"), _T ("\xe7\x43\x44\x83\x45\xea\x4e\xee\x52\x53\x54\xf2\x55\x59\x5a\x4c\x52\x4c\xef\x85\x86\x80\x87\x63\x64\x8e\x65\x92\x6e\x97\x72\x73\x74\x9c\x75\x79\x7a\x6c\x72\x6c\x99\x9a\x9f\x8a\xa7\xa4\x26\x5c\x22\x3c\x3e\xaa\xca\x20\xa9\xa8\xa1\xb1\xa6\x20\x20\x20\x20\x20\xaf\xd6\xbf")},
+  {_T ("MACCE"), _T ("\xe7\x89\x91\x83\x9d\xea\xc5\xee\xdb\xe1\xe8\xf2\xf1\xf8\xeb\xbb\xd9\xbd\xef\x85\x86\x80\x87\x8b\x93\x8e\x9e\x92\xcb\x97\xde\xe4\xe9\x9c\xf3\xf9\xec\xbc\xda\xbe\x99\x9a\x9f\x8a\xa7\xa4\x26\x5c\x22\x3c\x3e\xaa\xca\x20\xa9\xa8\xa1\xb1\xa6\x20\x20\x20\x20\x20\xaf\xd6\xbf")},
+  {_T ("CORK"), _T ("\xc1\x83\x84\xc9\x85\xcd\x8c\xd3\x90\x92\x94\xda\x97\xdd\x9a\x89\x8f\x88\xd4\xd6\xdc\xc4\xe1\xa3\xa4\xe9\xa5\xed\xac\xf3\xb0\xb2\xb4\xfa\xb7\xfd\xba\xa9\xaf\xa8\xf4\xf6\xfc\xe4\x73\x53\x26\x5c\x22\x3c\x3e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xd8\x20\xf8")}
+};
+
+bool alphabet_only;
+int chars_count;
+
+void
+str_fill (LPTSTR s, TCHAR ch, long count)
+{
+  while (count--)
+    *s++ = ch;
+  *s = _T ('\0');
+}
+
+long
+str_pos (LPCTSTR whole, LPCTSTR piece)
+{
+  LPCTSTR s = whole;
+  long l = _tcslen (piece);
+
+  while (*s)
+    if (!_tcsnicmp (s++, piece, l))
+      return s - whole - 1;
+  return -2;
+}
+
+bool
+str_same (LPCTSTR str1, LPCTSTR str2, long count)
+{
+  if (!count)
+    return false;
+  while (count--)
+    if (*str1++ != *str2++)
+      return false;
+  return true;
+}
+
+LPCTSTR
+skip_spaces (LPCTSTR s)
+{
+  while (*s)
+    if (*s == _T (' ') || *s == _T ('\t') || *s == _T ('\r') || *s == _T ('\n'))
+      s++;
+    else
+      break;
+  return s;
+}
+
+LPCTSTR
+skip_word (LPCTSTR s)
+{
+  s = skip_spaces (s);
+  while (*s)
+    if (*s != _T (' ') && *s != _T ('\t') && *s != _T ('\r') && *s != _T ('\n') && *s != _T ('='))
+      s++;
+    else
+      break;
+  return skip_spaces (s);
+}
+
+long
+get_coding (LPCTSTR name, type_codes *codes, int *coding)
+{
+  long i, pos;
+
+  for (i = 0; i < codes_count; i++)
+    if ((pos = str_pos (name, codes[i].name)) >= 0)
+      {
+        *coding = i;
+        return pos;
+      }
+  *coding = -2;
+  return -2;
+}
+
+long
+fget_coding (LPCTSTR text, int *coding)
+{
+  long posit, i;
+  LPCTSTR s, s1;
+
+  while ((i = str_pos (text, FD_ENCODING_LBRACKET)) >= 0)
+    {
+      s = text + i;
+
+      if ((i = str_pos (s, FD_ENCODING_LBRACKET FD_ENCODING_MARK)) >= 0)
+        posit += (s += _tcslen (FD_ENCODING_LBRACKET)) - text;
+      else if (*(s = skip_word (s1 = s)) != _T ('\0'))
+        posit += s - text;
+      if ((i = str_pos (s, FD_ENCODING_MARK)) >= 0)
+        {
+          if (*(s = skip_word ((s1 = s) + i)) != _T ('\0'))
+            posit += s - s1;
+          if (*s == _T ('='))
+            {
+              if (*(s = skip_spaces ((s1 = s) + 1)) != _T ('\0'))
+                posit += s - s1;
+              i = get_coding (s, source_codes, coding);
+              if (i >= 0)
+                return posit + i;
+            }
+        }
+    }
+  *coding = -2;
+  return -2;
+}
+
+TCHAR iconvert_char (TCHAR ch, int source_coding, int destination_coding, bool alphabet_only)
+  {
+    long i;
+    LPCTSTR source_chars, destination_chars;
+  
+    if (source_coding < 0)
+      return ch;
+    if (destination_coding < 0)
+      return ch;
+  
+    chars_count = alphabet_only ? chars_alphabet_count : chars_all_count;
+    source_chars = source_codes[source_coding].codes;
+    destination_chars = destination_codes[destination_coding].codes;
+    i = chars_count;
+    if ((unsigned) ch > 127)
+      for (i = 0; i < chars_count; i++)
+        if (ch == source_chars[i])
+          break;
+    return i < chars_count ? destination_chars[i] : ch;
+  }
+
+int
+iconvert (LPTSTR string, int source_coding, int destination_coding, bool alphabet_only)
+  {
+    long posit = -2, i, j;
+    LPCTSTR source_chars, destination_chars, cod_pos = NULL;
+    TCHAR ch;
+    LPTSTR s = string;
+  
+    if (source_coding < 0)
+      {
+        posit = fget_coding (string, &source_coding);
+        if (posit)
+          cod_pos = string + posit;
+      }
+    if (source_coding < 0)
+      return -1;
+    if (destination_coding < 0)
+      return -2;
+  
+    chars_count = alphabet_only ? chars_alphabet_count : chars_all_count;
+    source_chars = source_codes[source_coding].codes;
+    destination_chars = destination_codes[destination_coding].codes;
+    for (;;)
+      if (cod_pos == s)
+        {
+          i = _tcslen (source_codes[source_coding].name);
+          j = _tcslen (destination_codes[destination_coding].name);
+          if (i != j)
+            memmove (s + j, s + i, _tcslen (s + i) + 1);
+          memcpy (s, destination_codes[destination_coding].name, j);
+          s += j;
+        }
+      else
+        {
+          ch = *s;
+          if (!ch)
+            break;
+          i = chars_count;
+          if ((unsigned) ch > 127)
+            for (i = 0; i < chars_count; i++)
+              if (ch == source_chars[i])
+                break;
+          if (i < chars_count)
+            {
+              ch = destination_chars[i];
+              *s = ch;
+            }
+          s++;
+        }
+      return 0;
+  }
+
+int
+iconvert_new (LPCTSTR source, LPTSTR *destination, int source_coding, int destination_coding, bool alphabet_only)
+  {
+    LPTSTR dest = (LPTSTR) malloc (_tcslen (source) + 1 + 10); /* reserved for MYCHARSET= replacement */
+    int result = -3;
+    if (dest)
+      {
+        _tcscpy (dest, source);
+        result = iconvert (dest, source_coding, destination_coding, alphabet_only);
+        if (!result)
+          {
+            *destination = dest;
+            return 0;
+          }
+        free (dest);
+      }
+    return result;
+  }
diff --git a/Src/editlib/cs2cs.h b/Src/editlib/cs2cs.h
new file mode 100644 (file)
index 0000000..ec94afb
--- /dev/null
@@ -0,0 +1,59 @@
+/* Ferda Prantl - character coding conversion engine  */
+
+#ifndef __CS2CS_H__INCLUDED__
+#define __CS2CS_H__INCLUDED__
+
+#define FD_CODE_ASCII      0
+#define FD_CODE_CP1250     1
+#define FD_CODE_CP1252     2
+#define FD_CODE_CP850      3
+#define FD_CODE_CP852      4
+#define FD_CODE_IBM852     5
+#define FD_CODE_ISO_8859_1 6
+#define FD_CODE_ISO_8859_2 7
+#define FD_CODE_KEYBCS2    8
+#define FD_CODE_KOI8_CS    9
+#define FD_CODE_MAC        10
+#define FD_CODE_MACCE      11
+#define FD_CODE_CORK       12
+#define FD_CODE_TEX1       13
+#define FD_CODE_TEX2       14
+#define FD_CODE_HTML1      15
+#define FD_CODE_HTML2      16
+#define FD_CODE_RTF1       17
+#define FD_CODE_RTF2       18
+
+#ifndef NULL
+#define NULL 0
+#endif /* NULL */
+
+#ifndef _T
+typedef char TCHAR;
+typedef const char *LPCTSTR;
+typedef char *LPTSTR;
+#define _T(x) x
+#define _tcscpy strcpy
+#define _tcslen strlen
+#define _tcsnicmp strnicmp
+#endif /* _T */
+
+#ifndef __cplusplus
+#define false 0
+#define true 1
+typedef int bool;
+#endif /* __cplusplus */
+
+typedef struct type_codes_t
+  {
+    LPCTSTR name, codes;
+  }
+type_codes;
+
+extern type_codes source_codes[];
+extern type_codes destination_codes[];
+
+TCHAR EDITPADC_CLASS iconvert_char (TCHAR ch, int source_coding, int destination_coding, bool alphabet_only);
+int EDITPADC_CLASS iconvert (LPTSTR string, int source_coding, int destination_coding, bool alphabet_only);
+int EDITPADC_CLASS iconvert_new (LPCTSTR source, LPTSTR *destination, int source_coding, int destination_coding, bool alphabet_only);
+
+#endif // __CS2CS_H__INCLUDED__
diff --git a/Src/editlib/dcl.cpp b/Src/editlib/dcl.cpp
new file mode 100644 (file)
index 0000000..3e728b5
--- /dev/null
@@ -0,0 +1,441 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    dcl.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  AutoCAD DCL syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszDclKeywordList[] =
+  {
+    _T ("boxed_column"),
+    _T ("boxed_radio_column"),
+    _T ("boxed_radio_row"),
+    _T ("boxed_row"),
+    _T ("button"),
+    _T ("column"),
+    _T ("concatenation"),
+    _T ("dialog"),
+    _T ("edit_box"),
+    _T ("image"),
+    _T ("list_box"),
+    _T ("paragraph"),
+    _T ("popup_list"),
+    _T ("radio_button"),
+    _T ("row"),
+    _T ("slider"),
+    _T ("spacer"),
+    _T ("text_part"),
+    _T ("text"),
+    _T ("toggle"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("spacer_0"),
+    _T ("spacer_1"),
+    _T ("default_button"),
+    _T ("retirement_button"),
+    _T ("ok_cancel_help_errtile"),
+    _T ("ok_cancel_help_info"),
+    _T ("ok_cancel"),
+    _T ("ok_cancel_err"),
+    _T ("ok_cancel_help"),
+    _T ("ok_only"),
+    _T ("ok_button"),
+    _T ("cancel_button"),
+    _T ("help_button"),
+    _T ("info_button"),
+    _T ("errtile"),
+    _T ("image_button"),
+    _T ("radio_column"),
+    _T ("radio_row"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T ("action"),
+    _T ("alignment"),
+    _T ("allow_accept"),
+    _T ("aspect_ratio"),
+    _T ("big_increment"),
+    _T ("children_alignment"),
+    _T ("children_fixed_height"),
+    _T ("children_fixed_width"),
+    _T ("edit_limit"),
+    _T ("edit_width"),
+    _T ("fixed_height"),
+    _T ("fixed_width"),
+    _T ("height"),
+    _T ("initial_focus"),
+    _T ("is_bold"),
+    _T ("is_cancel"),
+    _T ("is_default"),
+    _T ("is_enabled"),
+    _T ("is_tab_stop"),
+    _T ("key"),
+    _T ("label"),
+    _T ("layout"),
+    _T ("list"),
+    _T ("max_value"),
+    _T ("min_value"),
+    _T ("mnemonic"),
+    _T ("multiple_select"),
+    _T ("small_increment"),
+    _T ("tabs"),
+    _T ("value"),
+    _T ("width"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsncmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsDclKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszDclKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsDclNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineDcl (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsDclKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                }
+              else if (IsDclNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '{' || pszChars[j] == ':')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (!bFunction)
+                    {
+                      for (int j = nIdentBegin; --j >= 0;)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == ':')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsDclKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsDclNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '{' || pszChars[j] == ':')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (!bFunction)
+            {
+              for (int j = nIdentBegin; --j >= 0;)
+                {
+                  if (!isspace (pszChars[j]))
+                    {
+                      if (pszChars[j] == ':')
+                        {
+                          bFunction = TRUE;
+                        }
+                      break;
+                    }
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/editcmd.h b/Src/editlib/editcmd.h
new file mode 100644 (file)
index 0000000..8875a06
--- /dev/null
@@ -0,0 +1,325 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by editres.rc
+//
+#define IDPREVIEW                       3
+#define IDD_ABOUTBOX                    100
+#define IDD_EDFILEOPEN                  101
+#define IDD_EDITOR_PAGE                 102
+#define IDB_LIGHTBULB                   102
+#define IDM_POPUP_HLINK                 103
+#define IDD_TIP                         103
+#define IDD_HLINK_PROPERTIES            105
+#define IDS_HLINK_PROPERTIES            105
+#define IDS_RICHED_LOAD_FAIL            108
+#define IDI_EDITPAD                     128
+#define IDI_EDITPADTYPE                 129
+#define IDC_HLINK                       130
+#define IDI_EDITPADRICHTYPE             130
+#define IDI_EDITPADBINTYPE              131
+#define IDC_HLINK_BAD                   131
+#define IDI_HLINK_URL                   132
+#define IDD_SPLASH                      157
+#define IDC_STATIC1                     158
+#define IDB_BITMAP48                    162
+#define IDS_TIP_DIDYOUKNOW              301
+#define IDS_TIP_FILE_ABSENT             302
+#define IDS_TIP_FILE_CORRUPT            303
+#define IDB_LIGHTBULB2                  344
+#define IDC_ME                          1000
+#define IDC_BULB                        1000
+#define IDC_ANDREI                      1001
+#define IDC_STARTUP                     1001
+#define IDR_POPUP_HEX_EDIT              1001
+#define IDC_SVEN                        1002
+#define IDC_INSERT_TABS                 1002
+#define IDC_NEXTTIP                     1002
+#define IDC_IMAGE                       1002
+#define IDC_STAS                        1003
+#define IDC_INSERT_SPACES               1003
+#define IDC_DESC                        1003
+#define IDC_MARKO                       1004
+#define IDC_TAB_SIZE                    1004
+#define IDC_TIPSTRING                   1004
+#define IDC_ADOLF                       1005
+#define IDC_NAME                        1005
+#define IDC_SHOW_TABS                   1005
+#define IDC_NUMBER                      1005
+#define IDC_FRANKY                      1006
+#define IDC_URL_PROMPT                  1006
+#define IDC_AUTOINDENT                  1006
+#define IDC_TEXT                        1006
+#define IDC_URL                         1007
+#define IDC_BACKSP_AT_BOL               1007
+#define IDC_ENCODING                    1007
+#define IDC_SELOM                       1008
+#define IDC_SEL_MARGIN                  1008
+#define IDC_FORMAT                      1008
+#define IDC_NONE                        1009
+#define IDC_ASP                         1010
+#define IDC_HANS                        1010
+#define IDC_BASIC                       1011
+#define IDC_MICHAEL                     1011
+#define IDC_BATCH                       1012
+#define IDC_ROBERTO                     1012
+#define IDC_C                           1013
+#define IDC_AUTODCL                     1014
+#define IDC_ROBERTO2                    1013
+#define IDC_JOSH                        1013
+#define IDC_FORTRAN                     1015
+#define IDC_EXTENSIONS                  1014
+#define IDC_JAN                         1014
+#define IDC_HTML                        1016
+#define IDC_PAUL                        1015
+#define IDC_INSTALLSHIELD               1017
+#define IDC_CRISTI                      1017
+#define IDC_JAVA                        1018
+#define IDC_AUTOLISP                    1019
+#define IDC_WITOLD                      1018
+#define IDC_MFCCODEGURU                 1019
+#define IDC_PASCAL                      1020
+#define IDC_PERL                        1021
+#define IDC_PHP                         1022
+#define IDC_PYTHON                      1023
+#define IDC_RSRC                        1024
+#define IDC_REXX                        1025
+#define IDC_BIGICON                     1023
+#define IDC_SGML                        1026
+#define IDC_SH                          1027
+#define IDC_SIOD                        1028
+#define IDC_SQL                         1029
+#define IDC_TCL                         1030
+#define IDC_TEX                         1031
+#define IDC_SELECT_ALL                  1032
+#define IDC_UNSELECT_ALL                1033
+#define IDC_BRACES_NO                   1032
+#define IDC_BRACES_ANSI                 1033
+#define IDC_BRACES_GNU                  1034
+#define IDC_EOLN_AUTO                   1035
+#define IDC_EOLN_DOS                    1036
+#define IDC_EOLN_UNIX                   1037
+#define IDC_EOLN_MAC                    1038
+#define IDC_FNBRACE                     1039
+#define IDC_WORDWRAP                    1040
+#define IDC_MORE                        1041
+#define IDC_EDITPAGE1                   1042
+#define IDC_SRC                         1043
+#define IDC_ALPHA_ONLY                  1044
+#define IDC_PREVIEW                     1045
+#define IDC_RECODE                      1046
+#define stc32                           0x045f
+#define IDD_EDIT_FIND                   8601
+#define IDD_EDIT_REPLACE                8602
+#define IDC_EDIT_WHOLE_WORD             8603
+#define IDD_EDIT_GOTO                   8603
+#define IDC_EDIT_MATCH_CASE             8604
+#define IDD_EDIT_CHARCONV               8604
+#define IDC_EDIT_TEXT                   8605
+#define IDD_EDITOR_PAGE1                8605
+#define IDC_EDIT_REGEXP                 8606
+#define IDS_EDIT_TEXT_NOT_FOUND         8606
+#define IDD_EDITOR_PAGE2                8606
+#define IDC_DEST                        8606
+#define IDC_EDIT_REPLACE                8607
+#define IDD_EDFILEADD                   8607
+#define IDC_EDIT_REPLACE_ALL            8608
+#define IDD_EDITOR_PAGE3                8608
+#define IDC_EDIT_REPLACE_WITH           8609
+#define IDC_EDIT_SKIP                   8610
+#define IDC_EDIT_DIRECTION_UP           8611
+#define IDC_EDIT_DIRECTION_DOWN         8612
+#define IDC_EDIT_SCOPE_SELECTION        8613
+#define IDC_EDIT_SCOPE_WHOLE_FILE       8614
+#define IDS_MENU_UNDO_FORMAT            8615
+#define IDS_MENU_REDO_FORMAT            8616
+#define IDS_MENU_UNDO_DEFAULT           8617
+#define IDS_MENU_REDO_DEFAULT           8618
+#define IDS_EDITOP_UNKNOWN              8619
+#define IDS_EDITOP_PASTE                8620
+#define IDS_EDITOP_DELSELECTION         8621
+#define IDS_EDITOP_CUT                  8622
+#define IDS_EDITOP_DELETE               8623
+#define IDS_EDITOP_TYPING               8624
+#define IDS_EDITOP_BACKSPACE            8625
+#define IDS_EDITOP_INDENT               8626
+#define IDS_EDITOP_DRAGDROP             8627
+#define IDS_EDITOP_REPLACE              8628
+#define IDS_EDITOP_AUTOINDENT           8629
+#define IDS_EDITOP_AUTOCOMPLETE         8630
+#define IDS_EDITOP_AUTOEXPAND           8631
+#define IDS_EDITOP_LOWERCASE            8632
+#define IDS_EDITOP_UPPERCASE            8633
+#define IDS_EDITOP_SWAPCASE             8634
+#define IDS_EDITOP_CAPITALIZE           8635
+#define IDS_EDITOP_SENTENCIZE           8636
+#define IDS_EDITOP_RECODE               8637
+#define IDS_EDITOP_SPELL                8638
+#define IDS_FIND_INCREMENTAL_FORWARD    8640
+#define IDS_FIND_INCREMENTAL_BACKWARD   8641
+#define IDS_FIND_INCREMENTAL_FAILED     8642
+#define IDS_SHEET_OPTIONS               8700
+#define IDR_MARGIN_CURSOR               22900
+#define IDR_DEFAULT_ACCEL               22901
+#define IDR_MARGIN_ICONS                22902
+#define IDR_RTF_ACCEL                   22903
+#define ID_EDIT_DELETE_WORD             32771
+#define ID_POPUP_EDIT                   32774
+#define ID_POPUP_PRINT                  32775
+#define ID_POPUP_OPEN                   32780
+#define ID_POPUP_COPYSHORTCUT           32781
+#define ID_POPUP_ADDTOFAVORITES         32782
+#define ID_POPUP_ADDTODESKTOP           32783
+#define ID_POPUP_PROPERTIES             32784
+#define ID_VIEW_FULL_SCREEN             32791
+#define ID_CHAR_BOLD                    32799
+#define ID_TOOLS_SPELLING               32800
+#define ID_TOOLS_SPELLING_SET           32801
+#define ID_CHAR_ITALIC                  32802
+#define ID_TOOLS_CHARCODING             32803
+#define ID_CHAR_UNDERLINE               32804
+#define ID_PARA_LEFT                    32805
+#define ID_PARA_CENTER                  32806
+#define ID_PARA_RIGHT                   32807
+#define ID_FILE_RELOAD                  36999
+#define ID_EDIT_FIRST                   37000
+#define ID_EDIT_DELETE                  37000
+#define ID_EDIT_DELETE_BACK             37001
+#define ID_EDIT_DELETE_WORD_BACK        37002
+#define ID_EDIT_TAB                     37003
+#define ID_EDIT_UNTAB                   37004
+#define ID_EDIT_SWITCH_OVRMODE          37005
+#define ID_EDIT_CHAR_LEFT               37100
+#define ID_EDIT_EXT_CHAR_LEFT           37101
+#define ID_EDIT_CHAR_RIGHT              37102
+#define ID_EDIT_EXT_CHAR_RIGHT          37103
+#define ID_EDIT_WORD_LEFT               37104
+#define ID_EDIT_EXT_WORD_LEFT           37105
+#define ID_EDIT_WORD_RIGHT              37106
+#define ID_EDIT_EXT_WORD_RIGHT          37107
+#define ID_EDIT_LINE_UP                 37108
+#define ID_EDIT_EXT_LINE_UP             37109
+#define ID_EDIT_LINE_DOWN               37110
+#define ID_EDIT_EXT_LINE_DOWN           37111
+#define ID_EDIT_SCROLL_UP               37112
+#define ID_EDIT_SCROLL_DOWN             37113
+#define ID_EDIT_PAGE_UP                 37114
+#define ID_EDIT_EXT_PAGE_UP             37115
+#define ID_EDIT_PAGE_DOWN               37116
+#define ID_EDIT_EXT_PAGE_DOWN           37117
+#define ID_EDIT_LINE_END                37118
+#define ID_EDIT_EXT_LINE_END            37119
+#define ID_EDIT_HOME                    37120
+#define ID_EDIT_EXT_HOME                37121
+#define ID_EDIT_TEXT_BEGIN              37122
+#define ID_EDIT_EXT_TEXT_BEGIN          37123
+#define ID_EDIT_TEXT_END                37124
+#define ID_EDIT_EXT_TEXT_END            37125
+#define ID_EDIT_FIND_PREVIOUS           37126
+#define ID_EDIT_TOGGLE_BOOKMARK0        37200
+#define ID_EDIT_TOGGLE_BOOKMARK1        37201
+#define ID_EDIT_TOGGLE_BOOKMARK2        37202
+#define ID_EDIT_TOGGLE_BOOKMARK3        37203
+#define ID_EDIT_TOGGLE_BOOKMARK4        37204
+#define ID_EDIT_TOGGLE_BOOKMARK5        37205
+#define ID_EDIT_TOGGLE_BOOKMARK6        37206
+#define ID_EDIT_TOGGLE_BOOKMARK7        37207
+#define ID_EDIT_TOGGLE_BOOKMARK8        37208
+#define ID_EDIT_TOGGLE_BOOKMARK9        37209
+#define ID_EDIT_GO_BOOKMARK0            37210
+#define ID_EDIT_GO_BOOKMARK1            37211
+#define ID_EDIT_GO_BOOKMARK2            37212
+#define ID_EDIT_GO_BOOKMARK3            37213
+#define ID_EDIT_GO_BOOKMARK4            37214
+#define ID_EDIT_GO_BOOKMARK5            37215
+#define ID_EDIT_GO_BOOKMARK6            37216
+#define ID_EDIT_GO_BOOKMARK7            37217
+#define ID_EDIT_GO_BOOKMARK8            37218
+#define ID_EDIT_GO_BOOKMARK9            37219
+#define ID_EDIT_CLEAR_BOOKMARKS         37220
+#define ID_EDIT_SET_BREAKPOINT          37221
+#define ID_EDIT_ENABLE_BREAKPOINT       37222
+#define ID_EDIT_TOGGLE_BOOKMARK         37223
+#define ID_EDIT_GOTO_NEXT_BOOKMARK      37224
+#define ID_EDIT_GOTO_PREV_BOOKMARK      37225
+#define ID_EDIT_CLEAR_ALL_BOOKMARKS     37226
+#define ID_EDIT_GOTO_LAST_CHANGE        37227
+#define ID_EDIT_FIND_INCREMENTAL_FORWARD 37228
+#define ID_EDIT_FIND_INCREMENTAL_BACKWARD 37229
+#define ID_EDIT_AUTOCOMPLETE            37300
+#define ID_EDIT_AUTOEXPAND              37301
+#define ID_EDIT_MATCHBRACE              37302
+#define ID_EDIT_LOWERCASE               37303
+#define ID_EDIT_UPPERCASE               37304
+#define ID_EDIT_CAPITALIZE              37305
+#define ID_EDIT_SENTENCE                37306
+#define ID_EDIT_SWAPCASE                37307
+#define ID_EDIT_GOTO                    37308
+#define ID_VIEW_OPTIONS                 37400
+#define ID_VIEW_TOGGLE_SRC_HDR          37401
+#define ID_VIEW_SELMARGIN               37402
+#define ID_DATE_TIME                    37403
+#define ID_VIEW_WORDWRAP                37404
+#define ID_READ_ONLY                    37405
+#define ID_SOURCE_PLAIN                 37500
+#define ID_SOURCE_ASP                   37501
+#define ID_SOURCE_BASIC                 37502
+#define ID_SOURCE_BATCH                 37503
+#define ID_SOURCE_C                     37504
+#define ID_SOURCE_AUTODCL               37505
+#define ID_SOURCE_FORTRAN               37506
+#define ID_SOURCE_HTML                  37507
+#define ID_SOURCE_INSTALLSHIELD         37508
+#define ID_SOURCE_JAVA                  37509
+#define ID_SOURCE_AUTOLISP              37510
+#define ID_SOURCE_PASCAL                37511
+#define ID_SOURCE_PERL                  37512
+#define ID_SOURCE_PHP                   37513
+#define ID_SOURCE_PYTHON                37514
+#define ID_SOURCE_REXX                  37515
+#define ID_SOURCE_RSRC                  37516
+#define ID_SOURCE_SGML                  37517
+#define ID_SOURCE_SH                    37518
+#define ID_SOURCE_SIOD                  37519
+#define ID_SOURCE_SQL                   37520
+#define ID_SOURCE_TCL                   37521
+#define ID_SOURCE_TEX                   37522
+#define ID_EDIT_INDICATOR_READ          37901
+#define ID_EDIT_INDICATOR_CRLF          37902
+#define ID_EDIT_INDICATOR_POSITION      37903
+#define ID_INDICATOR_TIME               37904
+#define ID_FORCE_REDRAW                 37999
+#define ID_EDIT_LAST                    37999
+#define ID_HELP_TIPOFTHEDAY             39000
+#define ID_FORMAT_SHOW_ADDRESS          40001
+#define ID_FORMAT_SHOW_HEX              40002
+#define ID_FORMAT_SHOW_ASCII            40003
+#define ID_FORMAT_WIDE_ADDRESS          40004
+#define ID_FORMAT_BPR_FIRST             40011
+#define ID_FORMAT_BPR_1                 40011
+#define ID_FORMAT_BPR_2                 40012
+#define ID_FORMAT_BPR_3                 40013
+#define ID_FORMAT_BPR_4                 40014
+#define ID_FORMAT_BPR_5                 40015
+#define ID_FORMAT_BPR_6                 40016
+#define ID_FORMAT_BPR_7                 40017
+#define ID_FORMAT_BPR_8                 40018
+#define ID_FORMAT_BPR_9                 40019
+#define ID_FORMAT_BPR_10                40020
+#define ID_FORMAT_BPR_11                40021
+#define ID_FORMAT_BPR_12                40022
+#define ID_FORMAT_BPR_13                40023
+#define ID_FORMAT_BPR_14                40024
+#define ID_FORMAT_BPR_15                40025
+#define ID_FORMAT_BPR_16                40026
+#define ID_FORMAT_BPR_LAST              40026
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        1002
+#define _APS_NEXT_COMMAND_VALUE         32772
+#define _APS_NEXT_CONTROL_VALUE         1049
+#define _APS_NEXT_SYMED_VALUE           1000
+#endif
+#endif
diff --git a/Src/editlib/editreg.h b/Src/editlib/editreg.h
new file mode 100644 (file)
index 0000000..95e85db
--- /dev/null
@@ -0,0 +1,38 @@
+////////////////////////////////////////////////////////////////////////////
+//  File:       editcmd.h
+//  Version:    1.2.0.5
+//  Created:    29-Dec-1998
+//
+//  Author:     Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Registry keys and values for Crystal Edit - syntax colorig text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  16-Aug-99
+//      Ferdinand Prantl:
+//  +   FEATURE: see cpps ...
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __EDITREG_H__INCLUDED__
+#define __EDITREG_H__INCLUDED__
+
+//  Registry keys & values
+#define REG_EDITPAD         _T ("Software\\EditPad")
+#define REG_EDITPAD_MULTI   _T ("Software\\EditPad\\Multi")
+#define REG_EDITPAD_SINGLE  _T ("Software\\EditPad\\Single")
+#define REG_EDITPAD_IDE     _T ("Software\\EditPad\\IDE")
+#define REG_EDITPAD_VERSION 0x0108000d
+#define MAX_REMEMBERED 100
+#define REMEMBERED_TO_REMOVE 10
+
+#endif // __EDITREG_H__INCLUDED__
diff --git a/Src/editlib/edtlib.cpp b/Src/editlib/edtlib.cpp
new file mode 100644 (file)
index 0000000..196a3b7
--- /dev/null
@@ -0,0 +1,57 @@
+// edtlib.cpp : Defines the initialization routines for the DLL.
+//
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+#include <afxdllx.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+HINSTANCE g_hDllInstance;
+
+static AFX_EXTENSION_MODULE EditpadcDLL = { NULL, NULL };
+
+extern "C" int APIENTRY
+DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+       // Remove this if you use lpReserved
+       UNREFERENCED_PARAMETER(lpReserved);
+        
+        CCrystalTextView::s_hResourceInst = hInstance;
+
+       if (dwReason == DLL_PROCESS_ATTACH)
+       {
+               TRACE0("EDITPADC.DLL Initializing!\n");
+               
+                g_hDllInstance = hInstance;
+                
+               // Extension DLL one-time initialization
+               if (!AfxInitExtensionModule(EditpadcDLL, hInstance))
+                       return 0;
+
+               // Insert this DLL into the resource chain
+               // NOTE: If this Extension DLL is being implicitly linked to by
+               //  an MFC Regular DLL (such as an ActiveX Control)
+               //  instead of an MFC application, then you will want to
+               //  remove this line from DllMain and put it in a separate
+               //  function exported from this Extension DLL.  The Regular DLL
+               //  that uses this Extension DLL should then explicitly call that
+               //  function to initialize this Extension DLL.  Otherwise,
+               //  the CDynLinkLibrary object will not be attached to the
+               //  Regular DLL's resource chain, and serious problems will
+               //  result.
+
+               new CDynLinkLibrary(EditpadcDLL);
+       }
+       else if (dwReason == DLL_PROCESS_DETACH)
+       {
+               TRACE0("EDITPADC.DLL Terminating!\n");
+               // Terminate the library before destructors are called
+               AfxTermExtensionModule(EditpadcDLL);
+       }
+       return 1;   // ok
+}
diff --git a/Src/editlib/edtlib.h b/Src/editlib/edtlib.h
new file mode 100644 (file)
index 0000000..d1b1aa4
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __EDTLIB_H
+#define __EDTLIB_H
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+
+
+#include "crystalparser.h"
+#include "ccrystaltextbuffer.h"
+#include "ccrystaltextview.h"
+#include "ccrystaleditview.h"
+#include "crystaleditviewex.h"
+
+#endif // __EDTLIB_H
diff --git a/Src/editlib/filesup.cpp b/Src/editlib/filesup.cpp
new file mode 100644 (file)
index 0000000..1c16038
--- /dev/null
@@ -0,0 +1,119 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    filesup.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Some handy stuff to deal with files and their names
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "filesup.h"
+
+#ifdef  _DEBUG
+#include "filesup.inl"
+#endif // _DEBUG
+
+#ifdef INLINE
+#undef INLINE
+#endif
+#define INLINE
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool FileExist(LPCTSTR lpszPath)
+{
+  CFileStatus status;
+  return CFile::GetStatus(lpszPath, status) != 0;
+}
+
+INLINE int
+GetExtPosition (LPCTSTR pszString)
+{
+  if (!pszString || !*pszString)
+    return 0;
+  const CString sString = pszString;
+  int len = sString.GetLength (), posit = len;
+  TCHAR test;
+  do
+    if ((test = sString.GetAt (--posit)) == _T ('.'))
+      return posit;
+  while (posit && test != _T ('\\') && test != _T (':'));
+  return len;
+}
+
+INLINE CString
+GetExt (CString sString)
+{
+  if (!sString.IsEmpty ())
+    {
+      sString = sString.Mid (GetExtPosition (sString));
+      if (!sString.IsEmpty () && sString[0] == _T ('.'))
+        {
+          sString = sString.Mid (1);
+        }
+    }
+  return sString;
+}
+
+INLINE CString
+GetName (const CString & sString)
+{
+  int nPosition = GetNamePosition (sString), nPosition2 = GetExtPosition (sString);
+
+  return sString.IsEmpty ()? sString : (nPosition2 == sString.GetLength ()? sString.Mid (nPosition) : sString.Mid (nPosition, nPosition2 - nPosition));
+}
+
+INLINE CString
+GetNameExt (const CString & sString)
+{
+  return sString.IsEmpty ()? sString : sString.Mid (GetNamePosition (sString));
+}
+
+INLINE int
+GetNamePosition (LPCTSTR pszString)
+{
+  if (!pszString || !*pszString)
+    return 0;
+  const CString sString = pszString;
+  int posit = sString.GetLength ();
+  TCHAR test;
+  do
+    if ((test = sString.GetAt (--posit)) == _T ('\\') || test == _T (':'))
+      return posit + 1;
+  while (posit);
+  return posit;
+}
+
+INLINE CString
+GetPath (const CString & sString, BOOL bClose /*= FALSE*/ )
+{
+  if (sString.IsEmpty ())
+    return sString;
+  int posit = GetNamePosition (sString);
+  if (posit == 0)
+    return bClose ? _T (".\\") : _T (".");
+
+  TCHAR test = sString.GetAt (posit - 1);
+
+  if (test == _T (':') || test == _T ('\\') && (posit == 1 || posit != 1 && sString.GetAt (posit - 2) == _T (':')))
+    return sString.Left (posit);
+  return sString.Left (bClose ? posit : test == _T (':') ? posit : posit - 1);
+}
+
+INLINE CString
+GetPathName (const CString & sString)
+{
+  int nPosition = GetExtPosition (sString);
+
+  return sString.IsEmpty ()? sString : (nPosition == sString.GetLength ()? sString : sString.Left (nPosition));
+}
+
+////////////////////////////////////////////////////////////////////////////////
diff --git a/Src/editlib/filesup.h b/Src/editlib/filesup.h
new file mode 100644 (file)
index 0000000..6f56293
--- /dev/null
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    filesup.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Some handy stuff to deal with files and their names
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __FILESUP_H__INCLUDED__
+#define __FILESUP_H__INCLUDED__
+
+/////////////////////////////////////////////////////////////////////////////
+
+bool EDITPADC_CLASS FileExist(LPCTSTR lpszPath);
+int EDITPADC_CLASS GetExtPosition (LPCTSTR pszString);
+CString EDITPADC_CLASS GetExt (CString sString);
+CString EDITPADC_CLASS GetName (const CString & sString);
+CString EDITPADC_CLASS GetNameExt (const CString & sString);
+int EDITPADC_CLASS GetNamePosition (LPCTSTR pszString);
+CString EDITPADC_CLASS GetPath (const CString & sString, BOOL bClose = FALSE);
+CString EDITPADC_CLASS GetPathName (const CString & sString);
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _DEBUG
+#include "filesup.inl"
+#endif // _DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // __FILESUP_H__INCLUDED__
diff --git a/Src/editlib/filesup.inl b/Src/editlib/filesup.inl
new file mode 100644 (file)
index 0000000..2033193
--- /dev/null
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    filesup.inl
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Some handy stuff to deal with files and their names
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __FILESUP_INL__INCLUDED__
+#define __FILESUP_INL__INCLUDED__
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef INLINE
+#undef INLINE
+#endif
+
+#ifndef _DEBUG
+#define INLINE inline
+#else
+#define INLINE
+#endif // _DEBUG
+
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // __FILESUP_INL__INCLUDED__
diff --git a/Src/editlib/fortran.cpp b/Src/editlib/fortran.cpp
new file mode 100644 (file)
index 0000000..58aac67
--- /dev/null
@@ -0,0 +1,449 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    fortran.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  FORTRAN syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszFortranKeywordList[] =
+  {
+    _T ("abs"),
+    _T ("achar"),
+    _T ("acos"),
+    _T ("adjustl"),
+    _T ("adjustr"),
+    _T ("aimag"),
+    _T ("aint"),
+    _T ("all"),
+    _T ("allocatable"),
+    _T ("allocate"),
+    _T ("allocated"),
+    _T (".and."),
+    _T ("anint"),
+    _T ("any"),
+    _T ("asin"),
+    _T ("assignment"),
+    _T ("associated"),
+    _T ("atan"),
+    _T ("atan2"),
+    _T ("backspace"),
+    _T ("bit_size"),
+    _T ("block"),
+    _T ("blockdata"),
+    _T ("btest"),
+    _T ("call"),
+    _T ("random_number"),
+    _T ("random_seed"),
+    _T ("system_clock"),
+    _T ("call"),
+    _T ("case"),
+    _T ("ceiling"),
+    _T ("char"),
+    _T ("character"),
+    _T ("close"),
+    _T ("cmplx"),
+    _T ("common"),
+    _T ("complex"),
+    _T ("conjg"),
+    _T ("contains"),
+    _T ("continue"),
+    _T ("cos"),
+    _T ("cosh"),
+    _T ("count"),
+    _T ("cshift"),
+    _T ("cycle"),
+    _T ("data"),
+    _T ("date_and_time"),
+    _T ("dble"),
+    _T ("deallocate"),
+    _T ("default"),
+    _T ("digits"),
+    _T ("dim"),
+    _T ("dimension"),
+    _T ("do"),
+    _T ("dot_product"),
+    _T ("double"),
+    _T ("doubleprecision"),
+    _T ("dprod"),
+    _T ("else"),
+    _T ("elseif"),
+    _T ("elsewhere"),
+    _T ("end"),
+    _T ("endblock"),
+    _T ("endblockdata"),
+    _T ("enddo"),
+    _T ("endfile"),
+    _T ("endif"),
+    _T ("endinterface"),
+    _T ("endselect"),
+    _T ("endtype"),
+    _T ("endwhere"),
+    _T ("entry"),
+    _T ("eoshift"),
+    _T ("epsilon"),
+    _T ("equivalence"),
+    _T ("exit"),
+    _T ("exp"),
+    _T ("exponent"),
+    _T ("external"),
+    _T ("file"),
+    _T ("floor"),
+    _T ("format."),
+    _T ("fraction"),
+    _T ("function"),
+    _T ("go"),
+    _T ("goto"),
+    _T ("huge"),
+    _T ("iachar"),
+    _T ("iand"),
+    _T ("ibclr"),
+    _T ("ibits"),
+    _T ("ibset"),
+    _T ("ichar"),
+    _T ("ieor"),
+    _T ("if"),
+    _T ("implicit"),
+    _T ("in"),
+    _T ("index"),
+    _T ("inout"),
+    _T ("inquire"),
+    _T ("int"),
+    _T ("integer"),
+    _T ("intent"),
+    _T ("interface"),
+    _T ("intrinsic"),
+    _T ("iolength"),
+    _T ("ior"),
+    _T ("ishftc"),
+    _T ("ishift"),
+    _T ("kind"),
+    _T ("lbound"),
+    _T ("len"),
+    _T ("len_trim"),
+    _T ("lge"),
+    _T ("lgt"),
+    _T ("lle"),
+    _T ("llt"),
+    _T ("log"),
+    _T ("log10"),
+    _T ("logical"),
+    _T ("matmul"),
+    _T ("max"),
+    _T ("maxexponent"),
+    _T ("maxloc"),
+    _T ("maxval"),
+    _T ("merge"),
+    _T ("min"),
+    _T ("minexponent"),
+    _T ("minloc"),
+    _T ("minval"),
+    _T ("mod"),
+    _T ("module"),
+    _T ("modulo"),
+    _T ("mvbits"),
+    _T ("namelist"),
+    _T ("nearest"),
+    _T ("nint"),
+    _T ("none"),
+    _T (".not."),
+    _T ("nullify"),
+    _T ("only"),
+    _T ("open"),
+    _T ("operator"),
+    _T ("optional"),
+    _T (".or."),
+    _T ("out"),
+    _T ("pack"),
+    _T ("parameter"),
+    _T ("pointer"),
+    _T ("precision"),
+    _T ("present"),
+    _T ("print"),
+    _T ("private"),
+    _T ("procedure"),
+    _T ("product"),
+    _T ("program"),
+    _T ("public"),
+    _T ("radix"),
+    _T ("rangereal"),
+    _T ("read"),
+    _T ("real"),
+    _T ("recursive"),
+    _T ("repeat"),
+    _T ("reshape"),
+    _T ("result"),
+    _T ("return"),
+    _T ("rewrind"),
+    _T ("rrspacing"),
+    _T ("save"),
+    _T ("scale"),
+    _T ("scan"),
+    _T ("select"),
+    _T ("selectcase"),
+    _T ("selected_int_kind"),
+    _T ("selected_real_kind"),
+    _T ("sequence"),
+    _T ("set_exponent"),
+    _T ("shape"),
+    _T ("sign"),
+    _T ("sin"),
+    _T ("sinh"),
+    _T ("size"),
+    _T ("spacing"),
+    _T ("spread"),
+    _T ("sqrt"),
+    _T ("stop"),
+    _T ("subroutine"),
+    _T ("sum"),
+    _T ("tan"),
+    _T ("tanh"),
+    _T ("target"),
+    _T ("then"),
+    _T ("tiny"),
+    _T ("to"),
+    _T ("transfer"),
+    _T ("transpose"),
+    _T ("trim"),
+    _T ("type"),
+    _T ("unbound"),
+    _T ("unpack"),
+    _T ("use"),
+    _T ("verify"),
+    _T ("where"),
+    _T ("while"),
+    _T ("write"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsFortranKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszFortranKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsFortranNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineFortran (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      if (pszChars[I] == '!' || !I && (pszChars[I] == 'C' || pszChars[I] == 'c'))
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsFortranKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsFortranNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsFortranKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsFortranNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/fpattern.cpp b/Src/editlib/fpattern.cpp
new file mode 100644 (file)
index 0000000..a9f9957
--- /dev/null
@@ -0,0 +1,402 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    fpattern.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl (I'm sorry, author unknown ...)
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  File-like string pattern matching routines
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "fpattern.h"
+
+#if TEST
+#define SUB     _T('~')
+#else
+#define SUB     FPAT_CLOSP
+#endif
+
+#ifndef DELIM
+#define DELIM       0
+#endif
+
+#define DEL     FPAT_DEL
+
+#ifdef __UNIX__
+#define DEL2            FPAT_DEL
+#define QUOTE           FPAT_QUOTE
+#define lowercase( c )  ( c )
+#else
+#define DEL2            FPAT_DEL2
+#define QUOTE           FPAT_QUOTE2
+#define lowercase( c )  _totlower( c )
+#endif
+
+/*-----------------------------------------------------------------------------
+ * fpattern_isvalid()
+ *  Checks that filename pattern 'pat' is a well-formed pattern.
+ *
+ * Returns
+ *  1 ( true ) if 'pat' is a valid filename pattern, otherwise 0 ( false ).
+ *
+ * Caveats
+ *  If 'pat' is null, 0 ( false ) is returned.
+ *
+ *  If 'pat' is empty ( "" ), 1 ( true ) is returned, and it is considered a
+ *  valid ( but degenerate ) pattern ( the only filename it matches is the
+ *  empty ( "" ) string ).
+ */
+
+int
+fpattern_isvalid (LPCTSTR pat)
+{
+  int len;
+
+  /* Check args */
+  if (pat == NULL)
+    return (FALSE);
+
+  /* Verify that the pattern is valid */
+  for (len = 0; pat[len] != _T('\0'); len++)
+    {
+      switch (pat[len])
+        {
+        case FPAT_SET_L:
+          /* Char set */
+          len++;
+          if (pat[len] == FPAT_SET_NOT)
+            len++;              /* Set negation */
+
+          while (pat[len] != FPAT_SET_R)
+            {
+              if (pat[len] == QUOTE)
+                len++;          /* Quoted char */
+              if (pat[len] == _T('\0'))
+                return (FALSE); /* Missing closing bracket */
+              len++;
+
+              if (pat[len] == FPAT_SET_THRU)
+                {
+                  /* Char range */
+                  len++;
+                  if (pat[len] == QUOTE)
+                    len++;      /* Quoted char */
+                  if (pat[len] == _T('\0'))
+                    return (FALSE);     /* Missing closing bracket */
+                  len++;
+                }
+
+              if (pat[len] == _T('\0'))
+                return (FALSE); /* Missing closing bracket */
+            }
+          break;
+
+        case QUOTE:
+          /* Quoted char */
+          len++;
+          if (pat[len] == _T('\0'))
+            return (FALSE);     /* Missing quoted char */
+          break;
+
+        case FPAT_NOT:
+          /* Negated pattern */
+          len++;
+          if (pat[len] == _T('\0'))
+            return (FALSE);     /* Missing subpattern */
+          break;
+
+        default:
+          /* Valid character */
+          break;
+        }
+    }
+
+  return (TRUE);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * fpattern_submatch()
+ *  Attempts to match subpattern 'pat' to subfilename 'fname'.
+ *
+ * Returns
+ *  1 ( true ) if the subfilename matches, otherwise 0 ( false ).
+ *
+ * Caveats
+ *  This does not assume that 'pat' is well-formed.
+ *
+ *  If 'pat' is empty ( "" ), the only filename it matches is the empty ( "" )
+ *  string.
+ *
+ *  Some non-empty patterns ( e.g., "" ) will match an empty filename ( "" ).
+ */
+
+static int
+fpattern_submatch (LPCTSTR pat, LPCTSTR fname)
+{
+  int fch;
+  int pch;
+  int i;
+  int yes, match;
+  int lo, hi;
+
+  /* Attempt to match subpattern against subfilename */
+  while (*pat != _T('\0'))
+    {
+      fch = *fname;
+      pch = *pat;
+      pat++;
+
+      switch (pch)
+        {
+        case FPAT_ANY:
+          /* Match a single char */
+#if DELIM
+          if (fch == DEL || fch == DEL2 || fch == _T('\0'))
+            return (FALSE);
+#else
+          if (fch == _T('\0'))
+            return (FALSE);
+#endif
+          fname++;
+          break;
+
+        case FPAT_CLOS:
+          /* Match zero or more chars */
+          i = 0;
+#if DELIM
+          while (fname[i] != _T('\0') &&
+                fname[i] != DEL && fname[i] != DEL2)
+            i++;
+#else
+          while (fname[i] != _T('\0'))
+            i++;
+#endif
+          while (i >= 0)
+            {
+              if (fpattern_submatch (pat, fname + i))
+                return (TRUE);
+              i--;
+            }
+          return (FALSE);
+
+        case SUB:
+          /* Match zero or more chars */
+          i = 0;
+          while (fname[i] != _T('\0') &&
+#if DELIM
+                fname[i] != DEL && fname[i] != DEL2 &&
+#endif
+                fname[i] != _T('.'))
+            i++;
+          while (i >= 0)
+            {
+              if (fpattern_submatch (pat, fname + i))
+                return (TRUE);
+              i--;
+            }
+          return (FALSE);
+
+        case QUOTE:
+          /* Match a quoted char */
+          pch = *pat;
+          if (lowercase (fch) != lowercase (pch) || pch == _T('\0'))
+            return (FALSE);
+          fname++;
+          pat++;
+          break;
+
+        case FPAT_SET_L:
+          /* Match char set/range */
+          yes = TRUE;
+          if (*pat == FPAT_SET_NOT)
+            {
+              pat++;
+              yes = FALSE;      /* Set negation */
+            }
+
+          /* Look for [ s ], [ - ], [ abc ], [ a-c ] */
+          match = !yes;
+          while (*pat != FPAT_SET_R && *pat != _T('\0'))
+            {
+              if (*pat == QUOTE)
+                pat++;          /* Quoted char */
+
+              if (*pat == _T('\0'))
+                break;
+              lo = *pat++;
+              hi = lo;
+
+              if (*pat == FPAT_SET_THRU)
+                {
+                  /* Range */
+                  pat++;
+
+                  if (*pat == QUOTE)
+                    pat++;      /* Quoted char */
+
+                  if (*pat == _T('\0'))
+                    break;
+                  hi = *pat++;
+                }
+
+              if (*pat == _T('\0'))
+                break;
+
+              /* Compare character to set range */
+              if (lowercase (fch) >= lowercase (lo) &&
+                    lowercase (fch) <= lowercase (hi))
+                match = yes;
+            }
+
+          if (!match)
+            return (FALSE);
+
+          if (*pat == _T('\0'))
+            return (FALSE);     /* Missing closing bracket */
+
+          fname++;
+          pat++;
+          break;
+
+        case FPAT_NOT:
+          /* Match only if rest of pattern does not match */
+          if (*pat == _T('\0'))
+            return (FALSE);     /* Missing subpattern */
+          i = fpattern_submatch (pat, fname);
+          return !i;
+
+#if DELIM
+        case DEL:
+#if DEL2 != DEL
+        case DEL2:
+#endif
+          /* Match path delimiter char */
+          if (fch != DEL && fch != DEL2)
+            return (FALSE);
+          fname++;
+          break;
+#endif
+
+        default:
+          /* Match a ( non-null ) char exactly */
+          if (lowercase (fch) != lowercase (pch))
+            return (FALSE);
+          fname++;
+          break;
+        }
+    }
+
+  /* Check for complete match */
+  if (*fname != _T('\0'))
+    return (FALSE);
+
+  /* Successful match */
+  return (TRUE);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * fpattern_match()
+ *  Attempts to match pattern 'pat' to filename 'fname'.
+ *
+ * Returns
+ *  1 ( true ) if the filename matches, otherwise 0 ( false ).
+ *
+ * Caveats
+ *  If 'fname' is null, zero ( false ) is returned.
+ *
+ *  If 'pat' is null, zero ( false ) is returned.
+ *
+ *  If 'pat' is empty ( "" ), the only filename it matches is the empty
+ *  string ( "" ).
+ *
+ *  If 'fname' is empty, the only pattern that will match it is the empty
+ *  string ( "" ).
+ *
+ *  If 'pat' is not a well-formed pattern, zero ( false ) is returned.
+ *
+ *  Upper and lower case letters are treated the same ; alphabetic
+ *  characters are converted to lower case before matching occurs.
+ *  Conversion to lower case is dependent upon the current locale setting.
+ */
+
+int
+fpattern_match (LPCTSTR pat, LPCTSTR fname)
+{
+  int rc;
+
+  /* Check args */
+  if (fname == NULL)
+    return (FALSE);
+
+  if (pat == NULL)
+    return (FALSE);
+
+  /* Verify that the pattern is valid, and get its length */
+  if (!fpattern_isvalid (pat))
+    return (FALSE);
+
+  /* Attempt to match pattern against filename */
+  if (fname[0] == _T('\0'))
+    return (pat[0] == _T('\0'));    /* Special case */
+  rc = fpattern_submatch (pat, fname);
+
+  return (rc);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * fpattern_matchn()
+ *  Attempts to match pattern 'pat' to filename 'fname'.
+ *  This operates like fpattern_match() except that it does not verify that
+ *  pattern 'pat' is well-formed, assuming that it has been checked by a
+ *  prior call to fpattern_isvalid().
+ *
+ * Returns
+ *  1 ( true ) if the filename matches, otherwise 0 ( false ).
+ *
+ * Caveats
+ *  If 'fname' is null, zero ( false ) is returned.
+ *
+ *  If 'pat' is null, zero ( false ) is returned.
+ *
+ *  If 'pat' is empty ( "" ), the only filename it matches is the empty ( "" )
+ *  string.
+ *
+ *  If 'pat' is not a well-formed pattern, unpredictable results may occur.
+ *
+ *  Upper and lower case letters are treated the same ; alphabetic
+ *  characters are converted to lower case before matching occurs.
+ *  Conversion to lower case is dependent upon the current locale setting.
+ *
+ * See also
+ *  fpattern_match().
+ */
+
+int
+fpattern_matchn (LPCTSTR pat, LPCTSTR fname)
+{
+  int rc;
+
+  /* Check args */
+  if (fname == NULL)
+    return (FALSE);
+
+  if (pat == NULL)
+    return (FALSE);
+
+  /* Assume that pattern is well-formed */
+
+  /* Attempt to match pattern against filename */
+  rc = fpattern_submatch (pat, fname);
+
+  return (rc);
+}
diff --git a/Src/editlib/fpattern.h b/Src/editlib/fpattern.h
new file mode 100644 (file)
index 0000000..310426d
--- /dev/null
@@ -0,0 +1,148 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    fpattern.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl (I'm sorry, author unknown ...)
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  File-like string pattern matching routines
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __FPATTERN_H__INCLUDED__
+#define __FPATTERN_H__INCLUDED__
+
+/******************************************************************************
+ * fpattern.h
+ *  Functions for matching filename patterns to filenames.
+ *
+ * Usage
+ *  Filename patterns are composed of regular (printable) characters which
+ *  may comprise a filename as well as special pattern matching characters:
+ *
+ *      .       Matches a period (.).
+ *          Note that a period in a filename is not treated any
+ *          differently than any other character.
+ *
+ *      ?       Any.
+ *          Matches any single character except '/' or '\'.
+ *
+ *      *       Closure.
+ *          Matches zero or more occurences of any characters other
+ *          than '/' or '\'.
+ *          Leading '*' characters are allowed.
+ *
+ *      SUB     Substitute (^Z).
+ *          Similar to '*', this matches zero or more occurences of
+ *          any characters other than '/', '\', or '.'.
+ *          Leading '^Z' characters are allowed.
+ *
+ *      [ab]    Set.
+ *          Matches the single character 'a' or 'b'.
+ *          If the dash '-' character is to be included, it must
+ *          immediately follow the opening bracket '['.
+ *          If the closing bracket ']' character is to be included,
+ *          it must be preceded by a quote '`'.
+ *
+ *      [a-z]   Range.
+ *          Matches a single character in the range 'a' to 'z'.
+ *          Ranges and sets may be combined within the same set of
+ *          brackets.
+ *
+ *      [!R]    Exclusive range.
+ *          Matches a single character not in the range 'R'.
+ *          If range 'R' includes the dash '-' character, the dash
+ *          must immediately follow the caret '!'.
+ *
+ *      !       Not.
+ *          Makes the following pattern (up to the next '/') match
+ *          any filename except those what it would normally match.
+ *
+ *      /       Path separator (UNIX and DOS).
+ *          Matches a '/' or '\' pathname (directory) separator.
+ *          Multiple separators are treated like a single
+ *          separator.
+ *          A leading separator indicates an absolute pathname.
+ *
+ *      \       Path separator (DOS).
+ *          Same as the '/' character.
+ *          Note that this character must be escaped if used within
+ *          string constants ("\\").
+ *
+ *      \       Quote (UNIX).
+ *          Makes the next character a regular (nonspecial)
+ *          character.
+ *          Note that to match the quote character itself, it must
+ *          be quoted.
+ *          Note that this character must be escaped if used within
+ *          string constants ("\\").
+ *
+ *      `       Quote (DOS).
+ *          Makes the next character a regular (nonspecial)
+ *          character.
+ *          Note that to match the quote character itself, it must
+ *          be quoted.
+ *
+ *  Upper and lower case alphabetic characters are considered identical,
+ *  i.e., 'a' and 'A' match each other.
+ *  (What constitutes a lowercase letter depends on the current locale
+ *  settings.)
+ *
+ *  Spaces and control characters are treated as normal characters.
+ *
+ * Examples
+ *  The following patterns in the left column will match the filenames in
+ *  the middle column and will not match filenames in the right column:
+ *
+ *      Pattern Will Match          Will Not Match
+ *      ------- ----------          --------------
+ *      a       a (only)            (anything else)
+ *      a.      a. (only)           (anything else)
+ *      a?c     abc, acc, arc, a.c      a, ac, abbc
+ *      a*c     ac, abc, abbc, acc, a.c     a, ab, acb, bac
+ *      a*      a, ab, abb, a., a.b     b, ba
+ *      *       a, ab, abb, a., .foo, a.foo (nothing)
+ *      *.      a., ab., abb., a.foo.       a, ab, a.foo, .foo
+ *      *.*     a., a.b, ah.bc.foo      a
+ *      ^Z      a, ab, abb          a., .foo, a.foo
+ *      ^Z.     a., ab., abb.           a, .foo, a.foo
+ *      ^Z.*    a, a., .foo, a.foo      ab, abb
+ *      *2.c    2.c, 12.c, foo2.c, foo.12.c 2x.c
+ *      a[b-z]c abc, acc, azc (only)        (anything else)
+ *      [ab0-9]x    ax, bx, 0x, 9x          zx
+ *      a[-.]b  a-b, a.b (only)         (anything else)
+ *      a[!a-z]b    a0b, a.b, a@b           aab, azb, aa0b
+ *      a[!-b]x a0x, a+x, acx           a-x, abx, axxx
+ *      a[-!b]x a-x, a!x, abx (only)        (anything else)
+ *      a[`]]x  a]x (only)          (anything else)
+ *      a``x    a`x (only)          (anything else)
+ *      oh`!    oh! (only)          (anything else)
+ *      is`?it  is?it (only)            (anything else)
+ *      !a?c    a, ac, ab, abb, acb, a.foo      abc, a.c, azc
+ *
+ */
+
+#define FPAT_QUOTE      _T('\\')    /* Quotes a special char    */
+#define FPAT_QUOTE2     _T('`') /* Quotes a special char    */
+#define FPAT_DEL        _T('/') /* Path delimiter       */
+#define FPAT_DEL2       _T('\\')    /* Path delimiter       */
+#define FPAT_DOT        _T('.') /* Dot char         */
+#define FPAT_NOT        _T('!') /* Exclusion            */
+#define FPAT_ANY        _T('?') /* Any one char         */
+#define FPAT_CLOS       _T('*') /* Zero or more chars       */
+#define FPAT_CLOSP      _T('\x1A')  /* Zero or more nondelimiters   */
+#define FPAT_SET_L      _T('[') /* Set/range open bracket   */
+#define FPAT_SET_R      _T(']') /* Set/range close bracket  */
+#define FPAT_SET_NOT    _T('!') /* Set exclusion        */
+#define FPAT_SET_THRU   _T('-') /* Set range of chars       */
+
+int EDITPADC_CLASS fpattern_isvalid (LPCTSTR pat);
+int EDITPADC_CLASS fpattern_match (LPCTSTR pat, LPCTSTR fname);
+int EDITPADC_CLASS fpattern_matchn (LPCTSTR pat, LPCTSTR fname);
+
+#endif // __FPATTERN_H__INCLUDED__
diff --git a/Src/editlib/gotodlg.cpp b/Src/editlib/gotodlg.cpp
new file mode 100644 (file)
index 0000000..b14cb13
--- /dev/null
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    gotodlg.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Go to line dialog
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "gotodlg.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CGotoDlg dialog
+
+CGotoDlg::CGotoDlg (CCrystalTextView * pBuddy):CDialog (CGotoDlg::IDD, NULL)
+{
+  m_pBuddy = pBuddy;
+  //{{AFX_DATA_INIT(CGotoDlg)
+  m_sNumber = _T ("");
+  //}}AFX_DATA_INIT
+}
+
+void CGotoDlg::
+DoDataExchange (CDataExchange * pDX)
+{
+  CDialog::DoDataExchange (pDX);
+  //{{AFX_DATA_MAP(CGotoDlg)
+  DDX_Control (pDX, IDC_NUMBER, m_ctlNumber);
+  DDX_Text (pDX, IDC_NUMBER, m_sNumber);
+  //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP (CGotoDlg, CDialog)
+//{{AFX_MSG_MAP(CGotoDlg)
+ON_EN_CHANGE (IDC_NUMBER, OnChangeNumber)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+/////////////////////////////////////////////////////////////////////////////
+// CGotoDlg message handlers
+
+void CGotoDlg::OnOK ()
+{
+  CDialog::OnOK ();
+  ASSERT (m_pBuddy != NULL);
+  m_pBuddy->GoToLine (_ttoi (m_sNumber), _tcschr (_T ("+-"), *(LPCTSTR)m_sNumber) != NULL);
+}
+
+void CGotoDlg::
+OnChangeNumber ()
+{
+  CString text;
+  GetDlgItem (IDC_NUMBER)->GetWindowText (text);
+  GetDlgItem (IDOK)->EnableWindow (!text.IsEmpty ());
+}
+
+BOOL CGotoDlg::
+OnInitDialog ()
+{
+  CDialog::OnInitDialog ();
+
+  GetDlgItem (IDOK)->EnableWindow (!m_sNumber.IsEmpty ());
+
+  return TRUE;
+}
diff --git a/Src/editlib/gotodlg.h b/Src/editlib/gotodlg.h
new file mode 100644 (file)
index 0000000..303a995
--- /dev/null
@@ -0,0 +1,70 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    gotodlg.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Go to line dialog
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __GOTODLG_H__INCLUDED__
+#define __GOTODLG_H__INCLUDED__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "editcmd.h"
+
+class CCrystalTextView;
+
+/////////////////////////////////////////////////////////////////////////////
+// CGotoDlg dialog
+
+class EDITPADC_CLASS CGotoDlg : public CDialog
+  {
+private :
+    CCrystalTextView * m_pBuddy;
+
+    // Construction
+public :
+    CGotoDlg (CCrystalTextView * pBuddy);
+
+    CPoint m_ptCurrentPos;
+    // Dialog Data
+    //{{AFX_DATA(CGotoDlg)
+       enum { IDD = IDD_EDIT_GOTO };
+    CEdit m_ctlNumber;
+    CString m_sNumber;
+    //}}AFX_DATA
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CGotoDlg)
+protected :
+    virtual void DoDataExchange (CDataExchange * pDX);    // DDX/DDV support
+    //}}AFX_VIRTUAL
+
+    // Implementation
+protected :
+
+    // Generated message map functions
+    //{{AFX_MSG(CGotoDlg)
+    virtual void OnOK ();
+    afx_msg void OnChangeNumber ();
+    virtual BOOL OnInitDialog ();
+    //}}AFX_MSG
+    DECLARE_MESSAGE_MAP ()
+  };
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // __GOTODLG_H__INCLUDED__
diff --git a/Src/editlib/html.cpp b/Src/editlib/html.cpp
new file mode 100644 (file)
index 0000000..e560c04
--- /dev/null
@@ -0,0 +1,701 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    html.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  HTML syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszHtmlKeywordList[] =
+  {
+    // HTML section
+    _T ("DOCTYPE"),
+    _T ("PUBLIC"),
+    _T ("FRAME"),
+    _T ("FRAMESET"),
+    _T ("NOFRAMES"),
+    // HEAD section
+    _T ("HEAD"),
+    _T ("TITLE"),
+    _T ("ISINDEX"),
+    _T ("META"),
+    _T ("LINK"),
+    _T ("BASE"),
+    _T ("SCRIPT"),
+    _T ("STYLE"),
+    // BODY section
+    _T ("BODY"),
+    // headings
+    _T ("H1"),
+    _T ("H2"),
+    _T ("H3"),
+    _T ("H4"),
+    _T ("H5"),
+    _T ("H6"),
+    // lists
+    _T ("UL"),
+    _T ("OL"),
+    _T ("DIR"),
+    _T ("MENU"),
+    _T ("LI"),
+    _T ("DL"),
+    _T ("DT"),
+    _T ("DD"),
+    // text containers
+    _T ("P"),
+    _T ("PRE"),
+    _T ("BLOCKQUOTE"),
+    _T ("ADDRESS"),
+    // others
+    _T ("DIV"),
+    _T ("SPAN"),
+    _T ("CENTER"),
+    _T ("HR"),
+    _T ("FORM"),
+    _T ("TABLE"),
+    _T ("LEFT"),
+    _T ("RIGHT"),
+    _T ("TOP"),
+    // logical markup
+    _T ("EM"),
+    _T ("STRONG"),
+    _T ("DFN"),
+    _T ("CODE"),
+    _T ("SAMP"),
+    _T ("KBD"),
+    _T ("VAR"),
+    _T ("CITE"),
+    // physical markup
+    _T ("TT"),
+    _T ("I"),
+    _T ("B"),
+    _T ("U"),
+    _T ("STRIKE"),
+    _T ("BIG"),
+    _T ("SMALL"),
+    _T ("SUB"),
+    _T ("SUP"),
+    // special markup
+    _T ("A"),
+    _T ("BASEFONT"),
+    _T ("IMG"),
+    _T ("APPLET"),
+    _T ("PARAM"),
+    _T ("FONT"),
+    _T ("BR"),
+    _T ("MAP"),
+    _T ("AREA"),
+    // forms
+    _T ("INPUT"),
+    _T ("SELECT"),
+    _T ("OPTION"),
+    _T ("TEXTAREA"),
+    _T ("ONCLICK"),
+    // tables
+    _T ("CAPTION"),
+    _T ("TR"),
+    _T ("TH"),
+    _T ("TD"),
+    _T ("HTML"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("ACTION"),
+    _T ("ALIGN"),
+    _T ("ALINK"),
+    _T ("BACKGROUND"),
+    _T ("BGCOLOR"),
+    _T ("COLOR"),
+    _T ("COMPACT"),
+    _T ("CONTENT"),
+    _T ("ENCTYPE"),
+    _T ("FACE"),
+    _T ("HEIGHT"),
+    _T ("HREF"),
+    _T ("HTTP-EQUIV"),
+    _T ("LINK"),
+    _T ("METHOD"),
+    _T ("NAME"),
+    _T ("PROMPT"),
+    _T ("REL"),
+    _T ("REV"),
+    _T ("START"),
+    _T ("TEXT"),
+    _T ("TYPE"),
+    _T ("VALUE"),
+    _T ("VLINK"),
+    _T ("WIDTH"),
+    _T ("ADD_DATE"),
+    _T ("ALT"),
+    _T ("BORDER"),
+    _T ("CELLPADDING"),
+    _T ("CELLSPACING"),
+    _T ("CHECKED"),
+    _T ("CLEAR"),
+    _T ("CODE"),
+    _T ("CODEBASE"),
+    _T ("COLS"),
+    _T ("COLSPAN"),
+    _T ("COORDS"),
+    _T ("FOLDED"),
+    _T ("HSPACE"),
+    _T ("ISMAP"),
+    _T ("LAST_MODIFIED"),
+    _T ("LAST_VISIT"),
+    _T ("MAXLENGTH"),
+    _T ("MULTIPLE"),
+    _T ("NORESIZE"),
+    _T ("NOSHADE"),
+    _T ("NOWRAP"),
+    _T ("ROWS"),
+    _T ("ROWSPAN"),
+    _T ("SELECTED"),
+    _T ("SHAPE"),
+    _T ("SIZE"),
+    _T ("SRC"),
+    _T ("TARGET"),
+    _T ("USEMAP"),
+    _T ("VALIGN"),
+    _T ("VSPACE"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T ("nbsp"),
+    _T ("quot"),
+    _T ("amp"),
+    _T ("lt"),
+    _T ("lt"),
+    _T ("gt"),
+    _T ("copy"),
+    _T ("reg"),
+    _T ("acute"),
+    _T ("laquo"),
+    _T ("raquo"),
+    _T ("iexcl"),
+    _T ("iquest"),
+    _T ("Agrave"),
+    _T ("agrave"),
+    _T ("Aacute"),
+    _T ("aacute"),
+    _T ("Acirc"),
+    _T ("acirc"),
+    _T ("Atilde"),
+    _T ("atilde"),
+    _T ("Auml"),
+    _T ("auml"),
+    _T ("Aring"),
+    _T ("aring"),
+    _T ("AElig"),
+    _T ("aelig"),
+    _T ("Ccedil"),
+    _T ("ccedil"),
+    _T ("ETH"),
+    _T ("eth"),
+    _T ("Egrave"),
+    _T ("egrave"),
+    _T ("Eacute"),
+    _T ("eacute"),
+    _T ("Ecirc"),
+    _T ("ecirc"),
+    _T ("Euml"),
+    _T ("euml"),
+    _T ("Igrave"),
+    _T ("igrave"),
+    _T ("Iacute"),
+    _T ("iacute"),
+    _T ("Icirc"),
+    _T ("icirc"),
+    _T ("Iuml"),
+    _T ("iuml"),
+    _T ("Ntilde"),
+    _T ("ntilde"),
+    _T ("Ograve"),
+    _T ("ograve"),
+    _T ("Oacute"),
+    _T ("oacute"),
+    _T ("Ocirc"),
+    _T ("ocirc"),
+    _T ("Otilde"),
+    _T ("otilde"),
+    _T ("Ouml"),
+    _T ("ouml"),
+    _T ("Oslash"),
+    _T ("oslash"),
+    _T ("Ugrave"),
+    _T ("ugrave"),
+    _T ("Uacute"),
+    _T ("uacute"),
+    _T ("Ucirc"),
+    _T ("ucirc"),
+    _T ("Uuml"),
+    _T ("uuml"),
+    _T ("Yacute"),
+    _T ("yacute"),
+    _T ("yuml"),
+    _T ("THORN"),
+    _T ("thorn"),
+    _T ("szlig"),
+    _T ("sect"),
+    _T ("para"),
+    _T ("micro"),
+    _T ("brvbar"),
+    _T ("plusmn"),
+    _T ("middot"),
+    _T ("uml"),
+    _T ("cedil"),
+    _T ("ordf"),
+    _T ("ordm"),
+    _T ("not"),
+    _T ("shy"),
+    _T ("macr"),
+    _T ("deg"),
+    _T ("sup1"),
+    _T ("sup2"),
+    _T ("sup3"),
+    _T ("frac14"),
+    _T ("frac12"),
+    _T ("frac34"),
+    _T ("times"),
+    _T ("divide"),
+    _T ("cent"),
+    _T ("pound"),
+    _T ("curren"),
+    _T ("yen"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsHtmlKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszHtmlKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsHtmlNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+#define COOKIE_USER1            0x0020
+#define COOKIE_EXT_USER1        0x0040
+
+DWORD CCrystalTextView::
+ParseLineHtml (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & (COOKIE_EXT_COMMENT|COOKIE_EXT_USER1);
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~(COOKIE_EXT_COMMENT|COOKIE_EXT_USER1)) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else if (dwCookie & COOKIE_EXT_USER1)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_FUNCNAME);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment <!--....-->
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          if (I > 1 && pszChars[I] == '>' && pszChars[I - 1] == '-' && pszChars[I - 2] == '-')
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment <?....?>
+      if (dwCookie & COOKIE_EXT_USER1)
+        {
+          if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+            {
+              dwCookie &= ~COOKIE_EXT_USER1;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if ((dwCookie & COOKIE_PREPROCESSOR) && pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+
+      if ((dwCookie & COOKIE_PREPROCESSOR) && pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength - 3 && pszChars[I] == '<' && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          I += 3;
+          dwCookie |= COOKIE_EXT_COMMENT;
+          dwCookie &= ~COOKIE_PREPROCESSOR;
+          continue;
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (dwCookie & COOKIE_PREPROCESSOR)
+                {
+                  if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                    }
+                  else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                    }
+                  else if (IsHtmlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              else if (dwCookie & COOKIE_USER1)
+                {
+                  if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+next:
+              ;
+            }
+
+          //  User1 start: <?
+          if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_FUNCNAME);
+              dwCookie |= COOKIE_EXT_USER1;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor start: < or bracket
+          if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && (pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')/* || pszChars[I] == '{'*/))
+            {
+              DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  User1 end: ?>
+          if (dwCookie & COOKIE_EXT_USER1)
+            {
+              if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+                {
+                  dwCookie &= ~COOKIE_EXT_USER1;
+                  nIdentBegin = -1;
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  continue;
+                }
+            }
+
+          //  Preprocessor end: > or bracket
+          if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              if (pszChars[I] == '>'/* || pszChars[I] == '}'*/)
+                {
+                  dwCookie &= ~COOKIE_PREPROCESSOR;
+                  nIdentBegin = -1;
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  continue;
+                }
+            }
+
+          //  Preprocessor start: &
+          if (pszChars[I] == '&')
+            {
+              dwCookie |= COOKIE_USER1;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor end: ;
+          if (dwCookie & COOKIE_USER1)
+            {
+              if (pszChars[I] == ';')
+                {
+                  dwCookie &= ~COOKIE_USER1;
+                  nIdentBegin = -1;
+                  continue;
+                }
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0 && (dwCookie & COOKIE_PREPROCESSOR))
+    {
+      if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsHtmlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  //  User1 start: <?
+  if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
+    {
+      DEFINE_BLOCK (I, COLORINDEX_FUNCNAME);
+      dwCookie |= COOKIE_EXT_USER1;
+      nIdentBegin = -1;
+      goto end;
+    }
+
+  //  Preprocessor start: < or {
+  if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && (pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')/* || pszChars[I] == '{'*/))
+    {
+      DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+      dwCookie |= COOKIE_PREPROCESSOR;
+      nIdentBegin = -1;
+      goto end;
+    }
+
+  //  User1 end: ?>
+  if (dwCookie & COOKIE_EXT_USER1)
+    {
+      if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+        {
+          dwCookie &= ~COOKIE_EXT_USER1;
+          nIdentBegin = -1;
+        }
+    }
+
+  //  Preprocessor end: > or }
+  if (dwCookie & COOKIE_PREPROCESSOR)
+    {
+      if (pszChars[I] == '>'/* || pszChars[I] == '}'*/)
+        {
+          dwCookie &= ~COOKIE_PREPROCESSOR;
+          nIdentBegin = -1;
+        }
+    }
+
+end:
+  dwCookie &= (COOKIE_EXT_COMMENT | COOKIE_STRING | COOKIE_PREPROCESSOR | COOKIE_EXT_USER1);
+  return dwCookie;
+}
diff --git a/Src/editlib/is.cpp b/Src/editlib/is.cpp
new file mode 100644 (file)
index 0000000..e532c17
--- /dev/null
@@ -0,0 +1,741 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:       is.cpp
+//  Version:    1.2.0.5
+//  Created:    29-Dec-1998
+//
+//  Copyright:  Stcherbatchenko Andrei
+//  E-mail:     windfall@gmx.de
+//
+//  Implementation of the CCrystalEditView class, a part of the Crystal Edit -
+//  syntax coloring text editor.
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  16-Aug-99
+//      Ferdinand Prantl:
+//  +   FEATURE: corrected bug in syntax highlighting C comments
+//  +   FEATURE: extended levels 1- 4 of keywords in some languages
+//
+//  ... it's being edited very rapidly so sorry for non-commented
+//        and maybe "ugly" code ...
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  InstallShield keywords (IS3.0)
+static LPTSTR s_apszISKeywordList[] =
+  {
+    _T ("begin"),
+    _T ("call"),
+    _T ("case"),
+    _T ("declare"),
+    _T ("default"),
+    _T ("downto"),
+    _T ("else"),
+    _T ("elseif"),
+    _T ("end"),
+    _T ("endif"),
+    _T ("endswitch"),
+    _T ("endwhile"),
+    _T ("external"),
+    _T ("for"),
+    _T ("function"),
+    _T ("goto"),
+    _T ("if"),
+    _T ("program"),
+    _T ("prototype"),
+    _T ("repeat"),
+    _T ("return"),
+    _T ("step"),
+    _T ("switch"),
+    _T ("then"),
+    _T ("to"),
+    _T ("typedef"),
+    _T ("until"),
+    _T ("void"),
+    _T ("while"),
+    _T ("BOOL"),
+    _T ("BYREF"),
+    _T ("CHAR"),
+    _T ("HIWORD"),
+    _T ("HWND"),
+    _T ("INT"),
+    _T ("LIST"),
+    _T ("LONG"),
+    _T ("LOWORD"),
+    _T ("NUMBER"),
+    _T ("POINTER"),
+    _T ("QUAD"),
+    _T ("RGB"),
+    _T ("SHORT"),
+    _T ("STRING"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("AFTER"),
+    _T ("APPEND"),
+    _T ("BACK"),
+    _T ("BEFORE"),
+    _T ("CANCEL"),
+    _T ("COMMAND"),
+    _T ("COMMANDEX"),
+    _T ("CONTINUE"),
+    _T ("DISABLE"),
+    _T ("DLG_ERR"),
+    _T ("ENABLE"),
+    _T ("EXCLUSIVE"),
+    _T ("EXISTS"),
+    _T ("FAILIFEXISTS"),
+    _T ("FALSE"),
+    _T ("FULL"),
+    _T ("NEXT"),
+    _T ("NO"),
+    _T ("NONEXCLUSIVE"),
+    _T ("NOSET"),
+    _T ("OFF"),
+    _T ("ON"),
+    _T ("PARTIAL"),
+    _T ("REPLACE"),
+    _T ("REPLACE_ITEM"),
+    _T ("RESET"),
+    _T ("RESTART"),
+    _T ("SET"),
+    _T ("TRUE"),
+    _T ("YES"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T ("CMDLINE"),
+    _T ("ERRORFILENAME"),
+    _T ("INFOFILENAME"),
+    _T ("ISRES"),
+    _T ("ISUSER"),
+    _T ("ISVERSION"),
+    _T ("SRCDIR"),
+    _T ("SRCDISK"),
+    _T ("SUPPORTDIR"),
+    _T ("TARGETDIR"),
+    _T ("TARGETDISK"),
+    _T ("WINDIR"),
+    _T ("WINDISK"),
+    _T ("WINSYSDIR"),
+    _T ("WINSYSDISK"),
+    NULL
+  };
+
+/* built-in functions
+    _T ("AddFolderIcon"),
+    _T ("AddProfString"),
+    _T ("AddressNumber"),
+    _T ("AddressString"),
+    _T ("AddressStruct"),
+    _T ("AppCommandControls"),
+    _T ("AskDestPath"),
+    _T ("AskOptionsCreates"),
+    _T ("AskPath"),
+    _T ("AskText"),
+    _T ("AskYesNoCreates"),
+    _T ("BatchAddAdds"),
+    _T ("BatchDeleteEx"),
+    _T ("BatchFileLoad"),
+    _T ("BatchFileSave"),
+    _T ("BatchFind"),
+    _T ("BatchGetFileNameRetrieves"),
+    _T ("BatchMoveEx"),
+    _T ("BatchSetFileNameDetermines"),
+    _T ("CallDLLFx"),
+    _T ("ChangeDirectory"),
+    _T ("CloseFile"),
+    _T ("CmdGetHwndDlg"),
+    _T ("CommitSharedFiles"),
+    _T ("ComponentAddItemAdds"),
+    _T ("ComponentDialog"),
+    _T ("ComponentGetItemInfoRetrieves"),
+    _T ("ComponentGetItemSizeQueries"),
+    _T ("ComponentIsItemSelected"),
+    _T ("ComponentListItemsCreates"),
+    _T ("ComponentSelectItem"),
+    _T ("ComponentSetItemInfoSets"),
+    _T ("ComponentTotalSizeCalculates"),
+    _T ("CompressAdd"),
+    _T ("CompressDel"),
+    _T ("CompressEnumEnumerates"),
+    _T ("CompressGet"),
+    _T ("CompressInfoRetrieves"),
+    _T ("ConfigAdd"),
+    _T ("ConfigDeleteDeletes"),
+    _T ("ConfigFileLoadLoads"),
+    _T ("ConfigFileSaveSaves"),
+    _T ("ConfigFindSearches"),
+    _T ("ConfigGetFileName"),
+    _T ("ConfigGetIntRetrieves"),
+    _T ("ConfigMoveMoves"),
+    _T ("ConfigSetFileName"),
+    _T ("ConfigSetIntSets"),
+    _T ("CopyBytes"),
+    _T ("CopyFileCopies"),
+    _T ("CreateDir"),
+    _T ("CreateFileCreates"),
+    _T ("CreateProgramFolder"),
+    _T ("CtrlClear"),
+    _T ("CtrlDir"),
+    _T ("CtrlGetCurSel"),
+    _T ("CtrlGetMLETextRetrieves"),
+    _T ("CtrlGetMultCurSel"),
+    _T ("CtrlGetStateRetrieves"),
+    _T ("CtrlGetSubCommand"),
+    _T ("CtrlGetText"),
+    _T ("CtrlPGroups"),
+    _T ("CtrlSelectTextSelects"),
+    _T ("CtrlSetCurSel"),
+    _T ("CtrlSetFont"),
+    _T ("CtrlSetList"),
+    _T ("CtrlSetMLETextSets"),
+    _T ("CtrlSetMultCurSel"),
+    _T ("CtrlSetStateSets"),
+    _T ("CtrlSetText"),
+    _T ("DefineDialogRegisters"),
+    _T ("DeinstallStartStarts"),
+    _T ("Delay"),
+    _T ("DeleteDir"),
+    _T ("DeleteFileDeletes"),
+    _T ("DeleteFolderIconRemoves"),
+    _T ("DeleteProgramFolder"),
+    _T ("Disable"),
+    _T ("DoInitiates"),
+    _T ("DoInstall"),
+    _T ("EnableEnables"),
+    _T ("EndDialog"),
+    _T ("EnterDisk"),
+    _T ("ExistsDir"),
+    _T ("ExistsDiskChecks"),
+    _T ("ExitProgMan"),
+    _T ("EzBatchAddPathAdds"),
+    _T ("EzBatchAddStringAdds"),
+    _T ("EzBatchReplaceReplaces"),
+    _T ("EzConfigAddDriver"),
+    _T ("EzConfigAddString"),
+    _T ("EzConfigGetValueRetrieves"),
+    _T ("EzConfigSetValueRetrieves"),
+    _T ("EzDefineDialogRegisters"),
+    _T ("FileCompare"),
+    _T ("FileDeleteLineDeletes"),
+    _T ("FileGrepSearches"),
+    _T ("FileInsertLineInserts"),
+    _T ("FileSetBeginDefineStarts"),
+    _T ("FileSetEndDefineEnds"),
+    _T ("FileSetEndPerform"),
+    _T ("FileSetPerformPerforms"),
+    _T ("FileSetPerformEzExecutes"),
+    _T ("FileSetResetResets"),
+    _T ("FileSetRoot"),
+    _T ("FindAllDirs"),
+    _T ("FindAllFilesSearches"),
+    _T ("FindFileSearches"),
+    _T ("FindWindowRetrieves"),
+    _T ("GetByte"),
+    _T ("GetDirRetrieves"),
+    _T ("GetDisk"),
+    _T ("GetDiskSpaceReturns"),
+    _T ("GetEnvVar"),
+    _T ("GetExtentsRetrieves"),
+    _T ("GetFileInfo"),
+    _T ("GetFont"),
+    _T ("GetGroupNameListRetrieves"),
+    _T ("GetItemNameList"),
+    _T ("GetLine"),
+    _T ("GetMemFreeReturns"),
+    _T ("GetMode"),
+    _T ("GetProfIntReturns"),
+    _T ("GetProfString"),
+    _T ("GetSystemInfo"),
+    _T ("GetValidDrivesListReturns"),
+    _T ("GetWindowHandle"),
+    _T ("Handler"),
+    _T ("HIWORDRetrieves"),
+    _T ("InstallationInfoAllows"),
+    _T ("IsRetrieves"),
+    _T ("LaunchApp"),
+    _T ("LaunchAppAndWaitLaunches"),
+    _T ("ListAddItem"),
+    _T ("ListAddString"),
+    _T ("ListCount"),
+    _T ("ListCreateCreates"),
+    _T ("ListCurrentItem"),
+    _T ("ListCurrentString"),
+    _T ("ListDeleteItemDeletes"),
+    _T ("ListDeleteStringDeletes"),
+    _T ("ListDestroy"),
+    _T ("ListFindItemAttempts"),
+    _T ("ListFindStringAttempts"),
+    _T ("ListGetFirstItemAcquires"),
+    _T ("ListGetFirstStringRetrieves"),
+    _T ("ListGetNextItem"),
+    _T ("ListGetNextString"),
+    _T ("ListReadFromFileReads"),
+    _T ("ListSetCurrentItemSets"),
+    _T ("ListSetCurrentStringSets"),
+    _T ("ListSetIndexSets"),
+    _T ("ListWriteToFile"),
+    _T ("LongPathFromShortPath"),
+    _T ("LongPathToQuote"),
+    _T ("LongPathToShortPath"),
+    _T ("LOWORDRetrieves"),
+    _T ("MessageBeep"),
+    _T ("MessageBoxCreates"),
+    _T ("NumToStrConverts"),
+    _T ("OpenFileOpens"),
+    _T ("OpenFileModeSets"),
+    _T ("ParsePath"),
+    _T ("PathAdd"),
+    _T ("PathDeleteDeletes"),
+    _T ("PathFindFinds"),
+    _T ("PathGet"),
+    _T ("PathMoveRearranges"),
+    _T ("PathSet"),
+    _T ("PlaceBitmap"),
+    _T ("PlaceWindow"),
+    _T ("QueryProgGroupQueries"),
+    _T ("QueryProgItem"),
+    _T ("QueryShellMgr"),
+    _T ("ReadBytes"),
+    _T ("RebootDialogCreates"),
+    _T ("RegDBCreateKeyExAllows"),
+    _T ("RegDBDeleteKeyDeletes"),
+    _T ("RegDBGetAppInfo"),
+    _T ("RegDBGetItemGets"),
+    _T ("RegDBGetKeyValueExRetrieves"),
+    _T ("RegDBKeyExist"),
+    _T ("RegDBQueryKey"),
+    _T ("RegDBSetAppInfo"),
+    _T ("RegDBSetDefaultRoot"),
+    _T ("RegDBSetItemSets"),
+    _T ("RegDBSetKeyValueExSets"),
+    _T ("ReleaseDialog"),
+    _T ("ReloadProgGroup"),
+    _T ("RenameFileRenames"),
+    _T ("ReplaceFolderIcon"),
+    _T ("ReplaceProfString"),
+    _T ("SdAskDestPath"),
+    _T ("SdAskOptionsCreates"),
+    _T ("SdAskOptionsListCreates"),
+    _T ("SdBitmapDisplays"),
+    _T ("SdComponentDialog"),
+    _T ("SdComponentDialog2Displays"),
+    _T ("SdComponentDialogAdvDisplays"),
+    _T ("SdComponentMult"),
+    _T ("SdConfirmNewDir"),
+    _T ("SdConfirmRegistration"),
+    _T ("SdDisplayTopics"),
+    _T ("SdFinishDisplays"),
+    _T ("SdFinishRebootDisplays"),
+    _T ("SdLicense"),
+    _T ("SdOptionsButtonsDisplays"),
+    _T ("SdProductName"),
+    _T ("SdRegisterUserDisplays"),
+    _T ("SdRegisterUserExDisplays"),
+    _T ("SdSelectFolderCreates"),
+    _T ("SdSetupType"),
+    _T ("SdShowAnyDialog"),
+    _T ("SdShowDlgEdit1Displays"),
+    _T ("SdShowDlgEdit2Displays"),
+    _T ("SdShowDlgEdit3Displays"),
+    _T ("SdShowFileModsDisplays"),
+    _T ("SdShowInfoListDisplays"),
+    _T ("SdShowMsg"),
+    _T ("SdStartCopy"),
+    _T ("SdWelcome"),
+    _T ("SeekBytes"),
+    _T ("SelectDir"),
+    _T ("SelectFolderCreates"),
+    _T ("SendMessage"),
+    _T ("SetByte"),
+    _T ("SetColorSets"),
+    _T ("SetDialogTitleChanges"),
+    _T ("SetErrorMsg"),
+    _T ("SetErrorTitle"),
+    _T ("SetFileInfo"),
+    _T ("SetFont"),
+    _T ("SetStatusWindow"),
+    _T ("SetTitleDisplays"),
+    _T ("SetupType"),
+    _T ("ShowGroup"),
+    _T ("ShowProgramFolder"),
+    _T ("SizeWindowSpecifies"),
+    _T ("Split"),
+    _T ("Sprintf"),
+    _T ("SprintfBoxAllows"),
+    _T ("StatusGetSize"),
+    _T ("StatusUpdateUpdates"),
+    _T ("StrCompareCompares"),
+    _T ("StrFind"),
+    _T ("StrGetTokensRetrieves"),
+    _T ("StrLength"),
+    _T ("StrRemoveLastSlashRemoves"),
+    _T ("StrSubExtracts"),
+    _T ("StrToLowerConverts"),
+    _T ("StrToNumConverts"),
+    _T ("StrToUpperConverts"),
+    _T ("StructGet"),
+    _T ("StructGetPPoints"),
+    _T ("StructPut"),
+    _T ("StructPutPPlaces"),
+    _T ("SystemTerminates"),
+    _T ("UnUseDLLUnloads"),
+    _T ("UseDLLOpens"),
+    _T ("VarRestoreRestores"),
+    _T ("VarSave"),
+    _T ("VerCompareCompares"),
+    _T ("VerFindFileVersionRetrieves"),
+    _T ("VerGetFileVersion"),
+    _T ("VerSearchAndUpdateFileSearches"),
+    _T ("VerUpdateFile"),
+    _T ("WaitOnDialogDisplays"),
+    _T ("Welcome"),
+    _T ("WriteBytesWrites"),
+    _T ("WriteLine"),
+    _T ("WriteProfString"),
+    _T ("XCopyFile"),
+*/
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsncmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsISKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszISKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsISNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineIS (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Preprocessor directive #....
+      if (dwCookie & COOKIE_PREPROCESSOR)
+        {
+          if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+            {
+              DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+              dwCookie |= COOKIE_EXT_COMMENT;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (pszChars[I] == '#')
+            {
+              DEFINE_BLOCK (I, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              continue;
+            }
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsISKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                }
+              else if (IsISNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsISKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsISNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/java.cpp b/Src/editlib/java.cpp
new file mode 100644 (file)
index 0000000..173a808
--- /dev/null
@@ -0,0 +1,378 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    java.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Java syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszJavaKeywordList[] =
+  {
+    _T ("abstract"),
+    _T ("default"),
+    _T ("goto"),
+    _T ("null"),
+    _T ("synchronized"),
+    _T ("boolean"),
+    _T ("do"),
+    _T ("if"),
+    _T ("package"),
+    _T ("this"),
+    _T ("break"),
+    _T ("double"),
+    _T ("implements"),
+    _T ("private"),
+    _T ("threadsafe"),
+    _T ("byte"),
+    _T ("else"),
+    _T ("import"),
+    _T ("protected"),
+    _T ("throw"),
+    _T ("byvalue"),
+    _T ("extends"),
+    _T ("instanceof"),
+    _T ("public"),
+    _T ("transient"),
+    _T ("case"),
+    _T ("false"),
+    _T ("int"),
+    _T ("return"),
+    _T ("true"),
+    _T ("catch"),
+    _T ("final"),
+    _T ("interface"),
+    _T ("short"),
+    _T ("try"),
+    _T ("char"),
+    _T ("finally"),
+    _T ("long"),
+    _T ("static"),
+    _T ("void"),
+    _T ("class"),
+    _T ("float"),
+    _T ("native"),
+    _T ("super"),
+    _T ("while"),
+    _T ("const"),
+    _T ("for"),
+    _T ("new"),
+    _T ("switch"),
+    _T ("continue"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsncmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsJavaKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszJavaKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsJavaNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineJava (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Preprocessor directive #....
+      if (dwCookie & COOKIE_PREPROCESSOR)
+        {
+          if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+            {
+              DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+              dwCookie |= COOKIE_EXT_COMMENT;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (pszChars[I] == '#')
+            {
+              DEFINE_BLOCK (I, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              continue;
+            }
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsJavaKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsJavaNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsJavaKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsJavaNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/lisp.cpp b/Src/editlib/lisp.cpp
new file mode 100644 (file)
index 0000000..0ae1e28
--- /dev/null
@@ -0,0 +1,576 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    lisp.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  LISP (particularly AutoLISP) syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszLispKeywordList[] =
+  {
+    _T ("abs"),
+    _T ("acad_colordlg"),
+    _T ("acad_helpdlg"),
+    _T ("acad_strlsort"),
+    _T ("action_tile"),
+    _T ("add_list"),
+    _T ("ads"),
+    _T ("alert"),
+    _T ("alloc"),
+    _T ("and"),
+    _T ("angle"),
+    _T ("angtof"),
+    _T ("angtos"),
+    _T ("append"),
+    _T ("apply"),
+    _T ("arxload"),
+    _T ("arxunload"),
+    _T ("arx"),
+    _T ("ascii"),
+    _T ("assoc"),
+    _T ("atan"),
+    _T ("atof"),
+    _T ("atoi"),
+    _T ("atoms-family"),
+    _T ("atom"),
+    _T ("autoarxload"),
+    _T ("autoload"),
+    _T ("autoxload"),
+    _T ("boole"),
+    _T ("boundp"),
+    _T ("caaaar"),
+    _T ("caaadr"),
+    _T ("caaar"),
+    _T ("caadar"),
+    _T ("caaddr"),
+    _T ("caadr"),
+    _T ("caar"),
+    _T ("cadaar"),
+    _T ("cadadr"),
+    _T ("cadar"),
+    _T ("caddar"),
+    _T ("cadddr"),
+    _T ("caddr"),
+    _T ("cadr"),
+    _T ("car"),
+    _T ("cdaaar"),
+    _T ("cdaadr"),
+    _T ("cdaar"),
+    _T ("cdadar"),
+    _T ("cdaddr"),
+    _T ("cdadr"),
+    _T ("cdar"),
+    _T ("cddaar"),
+    _T ("cddadr"),
+    _T ("cddar"),
+    _T ("cdddar"),
+    _T ("cddddr"),
+    _T ("cdddr"),
+    _T ("cddr"),
+    _T ("cdr"),
+    _T ("chr"),
+    _T ("client_data_tile"),
+    _T ("close"),
+    _T ("command"),
+    _T ("cond"),
+    _T ("cons"),
+    _T ("cos"),
+    _T ("cvunit"),
+    _T ("defun"),
+    _T ("dictnext"),
+    _T ("dictsearch"),
+    _T ("dimx_tile"),
+    _T ("dimy_tile"),
+    _T ("distance"),
+    _T ("distof"),
+    _T ("done_dialog"),
+    _T ("end_image"),
+    _T ("end_list"),
+    _T ("entdel"),
+    _T ("entget"),
+    _T ("entlast"),
+    _T ("entmake"),
+    _T ("entmod"),
+    _T ("entnext"),
+    _T ("entsel"),
+    _T ("entupd"),
+    _T ("equal"),
+    _T ("eq"),
+    _T ("eval"),
+    _T ("exit"),
+    _T ("expand"),
+    _T ("expt"),
+    _T ("exp"),
+    _T ("fill_image"),
+    _T ("findfile"),
+    _T ("fix"),
+    _T ("float"),
+    _T ("foreach"),
+    _T ("gcd"),
+    _T ("gc"),
+    _T ("get_attr"),
+    _T ("get_tile"),
+    _T ("getangle"),
+    _T ("getcfg"),
+    _T ("getcorner"),
+    _T ("getdist"),
+    _T ("getenv"),
+    _T ("getfield"),
+    _T ("getint"),
+    _T ("getkword"),
+    _T ("getorient"),
+    _T ("getpoint"),
+    _T ("getreal"),
+    _T ("getstring"),
+    _T ("getvar"),
+    _T ("graphscr"),
+    _T ("grclear"),
+    _T ("grdraw"),
+    _T ("grread"),
+    _T ("grtext"),
+    _T ("grvecs"),
+    _T ("handent"),
+    _T ("if"),
+    _T ("help"),
+    _T ("initget"),
+    _T ("inters"),
+    _T ("itoa"),
+    _T ("lambda"),
+    _T ("last"),
+    _T ("length"),
+    _T ("listp"),
+    _T ("list"),
+    _T ("load_dialog"),
+    _T ("load"),
+    _T ("logand"),
+    _T ("logior"),
+    _T ("log"),
+    _T ("lsh"),
+    _T ("mapcar"),
+    _T ("max"),
+    _T ("member"),
+    _T ("mem"),
+    _T ("menucmd"),
+    _T ("minusp"),
+    _T ("min"),
+    _T ("mode_tile"),
+    _T ("namedobjdict"),
+    _T ("nentsel"),
+    _T ("nentselp"),
+    _T ("new_dialog"),
+    _T ("not"),
+    _T ("nth"),
+    _T ("null"),
+    _T ("numberp"),
+    _T ("open"),
+    _T ("or"),
+    _T ("osnap"),
+    _T ("polar"),
+    _T ("prin1"),
+    _T ("princ"),
+    _T ("print"),
+    _T ("progn"),
+    _T ("prompt"),
+    _T ("quit"),
+    _T ("quote"),
+    _T ("read-char"),
+    _T ("read-line"),
+    _T ("read"),
+    _T ("redraw"),
+    _T ("regapp"),
+    _T ("rem"),
+    _T ("repeat"),
+    _T ("reverse"),
+    _T ("rtos"),
+    _T ("setcfg"),
+    _T ("setfunhelp"),
+    _T ("setq"),
+    _T ("setvar"),
+    _T ("set_tile"),
+    _T ("set"),
+    _T ("sin"),
+    _T ("slide_image"),
+    _T ("snvalid"),
+    _T ("sqrt"),
+    _T ("ssadd"),
+    _T ("ssdel"),
+    _T ("ssget"),
+    _T ("sslength"),
+    _T ("ssmemb"),
+    _T ("ssname"),
+    _T ("startapp"),
+    _T ("start_dialog"),
+    _T ("start_image"),
+    _T ("start_list"),
+    _T ("strcase"),
+    _T ("strcat"),
+    _T ("strlen"),
+    _T ("substr"),
+    _T ("subst"),
+    _T ("tablet"),
+    _T ("tblnext"),
+    _T ("tblobjname"),
+    _T ("tblsearch"),
+    _T ("term_dialog"),
+    _T ("terpri"),
+    _T ("textbox"),
+    _T ("textpage"),
+    _T ("textscr"),
+    _T ("trace"),
+    _T ("trans"),
+    _T ("type"),
+    _T ("unload_dialog"),
+    _T ("untrace"),
+    _T ("vector_image"),
+    _T ("ver"),
+    _T ("vmon"),
+    _T ("vports"),
+    _T ("wcmatch"),
+    _T ("while"),
+    _T ("write-char"),
+    _T ("write-line"),
+    _T ("xdroom"),
+    _T ("xdsize"),
+    _T ("xload"),
+    _T ("xunload"),
+    _T ("zerop"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsncmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsLispKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszLispKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsLispNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineLisp (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  BOOL bDefun = FALSE;
+
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == ';' && pszChars[I - 1] == '|')
+          if ((I > 1 && pszChars[I] == ';' && pszChars[I - 1] == '|' /*&& pszChars[I - 2] != ';'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == ';' && pszChars[I - 1] == '|'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] != '|' && pszChars[I - 1] == ';')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '|' && pszChars[I - 1] == ';')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsLispKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  if (!_tcsnicmp (_T ("defun"), pszChars + nIdentBegin, 5))
+                    {
+                      bDefun = TRUE;
+                    }
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsLispNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  if (!bDefun)
+                    {
+                      for (int j = nIdentBegin; --j >= 0;)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == '(')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                    }
+                  if (!bFunction)
+                    {
+                      for (int j = I; j >= 0; j--)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == '(')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsLispKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          if (!_tcsnicmp (_T ("defun"), pszChars + nIdentBegin, 5))
+            {
+              bDefun = TRUE;
+            }
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsLispNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          if (!bDefun)
+            {
+              for (int j = nIdentBegin; --j >= 0;)
+                {
+                  if (!isspace (pszChars[j]))
+                    {
+                      if (pszChars[j] == '(')
+                        {
+                          bFunction = TRUE;
+                        }
+                      break;
+                    }
+                }
+            }
+          if (!bFunction)
+            {
+              for (int j = I; j >= 0; j--)
+                {
+                  if (!isspace (pszChars[j]))
+                    {
+                      if (pszChars[j] == '(')
+                        {
+                          bFunction = TRUE;
+                        }
+                      break;
+                    }
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/memcombo.cpp b/Src/editlib/memcombo.cpp
new file mode 100644 (file)
index 0000000..e0d3963
--- /dev/null
@@ -0,0 +1,276 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    memcombo.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Combo-box saving last typed expressions
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+#include "memcombo.h"
+#include "registry.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define REMEMBER_COUNT  64
+
+#ifdef  _DEBUG
+#include "memcombo.inl"
+#endif // _DEBUG
+
+#ifdef INLINE
+#undef INLINE
+#endif
+#define INLINE
+
+/////////////////////////////////////////////////////////////////////////////
+// CMemComboBox
+
+BEGIN_MESSAGE_MAP (CMemComboBox, CComboBox)
+//{{AFX_MSG_MAP(CMemComboBox)
+ON_WM_KILLFOCUS ()
+ON_CONTROL_REFLECT (CBN_SETFOCUS, OnSetfocus)
+ON_WM_DESTROY ()
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+/////////////////////////////////////////////////////////////////////////////
+// CMemComboBox message handlers
+
+CMap < CString, LPCTSTR, CString, LPCTSTR > CMemComboBox::groups;
+
+void SetComboBoxHeight(CComboBox &Control)
+{
+       int                     nHeight = Control.GetCount(), nMax = ::GetSystemMetrics(SM_CYSCREEN) - 48;
+       CRect           rc;
+
+       Control.GetClientRect(rc);
+       Control.ClientToScreen(rc);
+       nHeight = rc.Height() * nHeight + 16;
+       if(rc.top + nHeight > nMax)
+               nHeight = nMax - rc.top;
+       Control.SetWindowPos(NULL, 0, 0, rc.Width(), nHeight, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREDRAW);
+}
+
+void SetComboBoxWidth(CComboBox &Control, LPCTSTR lpszText = NULL)
+{
+       int                                     cnt = Control.GetCount();
+
+       if(!cnt)
+               return;
+       CClientDC                       dc(&Control);
+       NONCLIENTMETRICS        info;
+       CFont                           oFont, *oldFont;
+       int                                     width = 0, nMax = ::GetSystemMetrics(SM_CXSCREEN) - 48;
+       CRect                           rc;
+       CSize                           size;
+
+       memset(&info.lfMenuFont, 0, sizeof(LOGFONT));
+       SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+       info.lfMenuFont.lfHeight = -MulDiv(9, dc.GetDeviceCaps(LOGPIXELSY), 72);
+       info.lfMenuFont.lfWidth = 0;
+       info.lfMenuFont.lfWeight = FW_THIN;
+       info.lfMenuFont.lfItalic = FALSE;
+       info.lfMenuFont.lfUnderline = FALSE;
+       info.lfMenuFont.lfCharSet = DEFAULT_CHARSET;
+       info.lfMenuFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+       info.lfMenuFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+       info.lfMenuFont.lfQuality = DEFAULT_QUALITY;
+       info.lfMenuFont.lfPitchAndFamily = FF_SWISS;
+       _tcscpy(info.lfMenuFont.lfFaceName, _T("MS Sans Serif"));
+       oFont.CreateFontIndirect(&info.lfMenuFont);
+       oldFont = dc.SelectObject(&oFont);
+       if(lpszText && *lpszText) {
+               size = dc.GetTextExtent(lpszText);
+               width = size.cx;
+       } else {
+               CString                         item;
+
+               for(int i = 0; i < cnt; i++) {
+                       Control.GetLBText(i, item);
+                       size = dc.GetTextExtent(item);
+                       if(size.cx > width)
+                               width = size.cx;
+               }
+       }
+       Control.GetClientRect(rc);
+       Control.ClientToScreen(rc);
+       if(rc.left + width > nMax)
+               width = nMax - rc.left;
+       Control.SetDroppedWidth(width);
+       dc.SelectObject(oldFont);
+}
+
+/*void FillComboBox(CComboBox &Control, const CList<CString, LPCTSTR> &Items, LPCTSTR lpszItem, BOOL bMustContains)
+{
+       POSITION        pos = Items.GetHeadPosition();
+       CString         item, maxitem;
+       int                     maxlen = 0, len;
+
+       Control.ResetContent();
+       while(pos) {
+               item = Items.GetNext(pos);
+               len = item.GetLength();
+               if(maxlen < len) {
+                       maxlen = len;
+                       maxitem = item;
+               }
+               Control.AddString(item);
+       }
+       if(Items.Find(lpszItem))
+               Control.SelectString(-1, lpszItem);
+       else if(!bMustContains)
+               Control.SetWindowText(lpszItem);
+       SetComboBoxHeight(Control);
+       SetComboBoxWidth(Control, maxitem);
+}*/
+
+/*int ListToString (CString &sResult, CList<CString, LPCTSTR> listSource)
+{
+  POSITION pos = listSource.GetHeadPosition ();
+  CString item;
+  while (pos)
+    {
+      item = listSource.GetNext (pos);
+      sResult += item + _T ('\n');
+    }
+  return listSource.GetCount ();
+}*/
+
+/*int StringToList (CList<CString, LPCTSTR> listResult, CString sSource)
+{
+  int pos;
+  while ((pos = sSource.Find (_T ('\n'))) != -1)
+    {
+      listResult.AddTail (sSource.Left (pos));
+      sSource = sSource.Mid (pos + 1);
+    }
+  if (*(LPCTSTR) sSource)
+    {
+      listResult.AddTail (sSource);
+    }
+  return listResult.GetCount ();
+}*/
+
+void CMemComboBox::FillCurrent ()
+{
+  CString strText;
+  GetWindowText (strText);
+  Fill (strText);
+}
+
+void CMemComboBox::
+Fill (LPCTSTR text)
+{
+  if (text && *text)
+    {
+      int nPos = FindStringExact (-1, text);
+      if (nPos  != CB_ERR)
+        DeleteString (nPos);
+      InsertString (0, text);
+      int l = GetCount ();
+      if (l > REMEMBER_COUNT)
+        DeleteString (--l);
+      SetComboBoxHeight (*this);
+      SetComboBoxWidth (*this);
+      SetCurSel (0);
+      if (!m_sGroup.IsEmpty ())
+        {
+          CString item, items;
+          for (int i = 0; i < l; i++)
+            {
+              GetLBText (i, item);
+              items += item + _T ('\n');
+            }
+          groups.SetAt (m_sGroup, items);
+        }
+    }
+}
+
+void CMemComboBox::
+LoadSettings ()
+{
+  CReg reg;
+  if (reg.Open (HKEY_CURRENT_USER, _T ("SOFTWARE\\EditPad"), KEY_READ))
+    {
+      POSITION pos = groups.GetStartPosition ();
+      static LPCTSTR name[] = { _T("FindText"), _T("ReplaceText") };
+      CString value;
+
+      for (int i = 0; i < countof (name); i++)
+        {
+          if (reg.LoadString (name[i], value))
+            {
+              groups.SetAt (name[i], value);
+            }
+        }
+    }
+}
+
+void CMemComboBox::
+SaveSettings ()
+{
+  CReg reg;
+  if (reg.Create (HKEY_CURRENT_USER, _T ("SOFTWARE\\EditPad"), KEY_WRITE))
+    {
+      POSITION pos = groups.GetStartPosition ();
+      CString name, value;
+
+      while (pos)
+        {
+          groups.GetNextAssoc (pos, name, value);
+          VERIFY (reg.SaveString (name, value));
+        }
+    }
+}
+
+void CMemComboBox::
+OnKillFocus (CWnd * /*pNewWnd*/)
+{
+  FillCurrent ();
+}
+
+void CMemComboBox::
+OnSetfocus ()
+{
+  if (m_bFirstFocus && !m_sGroup.IsEmpty ())
+    {
+      m_bFirstFocus = FALSE;
+      CString items, strText;
+      GetWindowText (strText);
+      if (groups.Lookup (m_sGroup, items))
+        {
+          int p;
+          while ((p = items.Find (_T ('\n'))) != -1)
+            {
+              AddString (items.Left (p));
+              items = items.Mid (p + 1);
+            }
+          SetComboBoxHeight (*this);
+          SetComboBoxWidth (*this);
+          SetCurSel (0);
+          if (!strText.IsEmpty ())
+            SetWindowText (strText);
+        }
+    }
+}
+
+void CMemComboBox::
+OnDestroy ()
+{
+  FillCurrent ();
+  CComboBox::OnDestroy ();
+}
diff --git a/Src/editlib/memcombo.h b/Src/editlib/memcombo.h
new file mode 100644 (file)
index 0000000..422c93a
--- /dev/null
@@ -0,0 +1,81 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    memcombo.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Combo-box saving last typed expressions
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __MEMCOMBO_H__INCLUDED__
+#define __MEMCOMBO_H__INCLUDED__
+
+////////////////////////////////////////////////////////////////////////////////
+// Includes
+
+////////////////////////////////////////////////////////////////////////////////
+// All Classes and Class Templates
+
+class CMemComboBox;
+
+////////////////////////////////////////////////////////////////////////////////
+// Includes
+
+/////////////////////////////////////////////////////////////////////////////
+// CMemComboBox Class Declaration
+
+class EDITPADC_CLASS CMemComboBox : public CComboBox
+  {
+    // Construction
+public :
+    CMemComboBox ();
+
+    // Attributes
+public :
+    static CMap < CString, LPCTSTR, CString, LPCTSTR > groups;
+    BOOL m_bFirstFocus;
+    CString m_sGroup;
+
+    // Operations
+public :
+    void FillCurrent ();
+    void Fill (LPCTSTR text);
+    static void LoadSettings ();
+    static void SaveSettings ();
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CMemComboBox)
+    //}}AFX_VIRTUAL
+
+    // Implementation
+public :
+    virtual ~CMemComboBox ();
+
+    // Generated message map functions
+public :
+    //{{AFX_MSG(CMemComboBox)
+    afx_msg void OnKillFocus (CWnd * pNewWnd);
+    afx_msg void OnSetfocus ();
+    afx_msg void OnDestroy ();
+    //}}AFX_MSG
+
+    DECLARE_MESSAGE_MAP ()
+  };
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _DEBUG
+#include "memcombo.inl"
+#endif // _DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // __MEMCOMBO_H__INCLUDED__
diff --git a/Src/editlib/memcombo.inl b/Src/editlib/memcombo.inl
new file mode 100644 (file)
index 0000000..91620bc
--- /dev/null
@@ -0,0 +1,45 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    memcombo.inl
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Combo-box saving last typed expressions
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __MEMCOMBO_INL__INCLUDED__
+#define __MEMCOMBO_INL__INCLUDED__
+
+#ifdef INLINE
+#undef INLINE
+#endif
+
+#ifndef _DEBUG
+#define INLINE inline
+#else
+#define INLINE
+#endif // _DEBUG
+
+////////////////////////////////////////////////////////////////////////////////
+// Methods
+
+INLINE
+CMemComboBox::CMemComboBox () : m_bFirstFocus (TRUE)
+{
+}
+
+INLINE
+CMemComboBox::~CMemComboBox ()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // __MEMCOMBO_INL__INCLUDED__
diff --git a/Src/editlib/pascal.cpp b/Src/editlib/pascal.cpp
new file mode 100644 (file)
index 0000000..24f69dd
--- /dev/null
@@ -0,0 +1,346 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    pascal.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Pascal syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszPascalKeywordList[] =
+  {
+    _T ("program"),
+    _T ("const"),
+    _T ("type"),
+    _T ("var"),
+    _T ("begin"),
+    _T ("end"),
+    _T ("array"),
+    _T ("set"),
+    _T ("record"),
+    _T ("string"),
+    _T ("if"),
+    _T ("then"),
+    _T ("else"),
+    _T ("while"),
+    _T ("for"),
+    _T ("to"),
+    _T ("downto"),
+    _T ("do"),
+    _T ("with"),
+    _T ("repeat"),
+    _T ("until"),
+    _T ("case"),
+    _T ("of"),
+    _T ("goto"),
+    _T ("exit"),
+    _T ("label"),
+    _T ("procedure"),
+    _T ("function"),
+    _T ("nil"),
+    _T ("file"),
+    _T ("and"),
+    _T ("or"),
+    _T ("not"),
+    _T ("xor"),
+    _T ("div"),
+    _T ("mod"),
+    _T ("unit"),
+    _T ("uses"),
+    _T ("implementation"),
+    _T ("interface"),
+    _T ("external"),
+    _T ("asm"),
+    _T ("inline"),
+    _T ("object"),
+    _T ("constructor"),
+    _T ("destructor"),
+    _T ("virtual"),
+    _T ("far"),
+    _T ("assembler"),
+    _T ("near"),
+    _T ("inherited"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsPascalKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszPascalKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsPascalNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLinePascal (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == ')' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == ')' && pszChars[I - 1] == '*' && pszChars[I - 2] != '(') || (I == 1 && pszChars[I] == ')' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '(')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          continue;
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsPascalKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsPascalNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsPascalKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsPascalNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/perl.cpp b/Src/editlib/perl.cpp
new file mode 100644 (file)
index 0000000..bc20703
--- /dev/null
@@ -0,0 +1,506 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    perl.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  PERL syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszPerlKeywordList[] =
+  {
+    _T ("q"),
+    _T ("qq"),
+    _T ("qw"),
+    _T ("qx"),
+    _T ("m"),
+    _T ("s"),
+    _T ("y"),
+    _T ("tr"),
+    _T ("if"),
+    _T ("sub"),
+    _T ("return"),
+    _T ("while"),
+    _T ("for"),
+    _T ("elsif"),
+    _T ("foreach"),
+    _T ("else"),
+    _T ("unless"),
+    _T ("eq"),
+    _T ("not"),
+    _T ("and"),
+    _T ("or"),
+    _T ("ne"),
+    _T ("until"),
+    _T ("abs"),
+    _T ("accept"),
+    _T ("alarm"),
+    _T ("atan2"),
+    _T ("bind"),
+    _T ("binmode"),
+    _T ("bless"),
+    _T ("caller"),
+    _T ("chdir"),
+    _T ("chmod"),
+    _T ("chomp"),
+    _T ("chop"),
+    _T ("chown"),
+    _T ("chr"),
+    _T ("chroot"),
+    _T ("close"),
+    _T ("closedir"),
+    _T ("connect"),
+    _T ("cos"),
+    _T ("crypt"),
+    _T ("dbmclose"),
+    _T ("dbmopen"),
+    _T ("defined"),
+    _T ("delete"),
+    _T ("die"),
+    _T ("do"),
+    _T ("dump"),
+    _T ("each"),
+    _T ("eof"),
+    _T ("eval"),
+    _T ("exec"),
+    _T ("exists"),
+    _T ("exit"),
+    _T ("exp"),
+    _T ("fcntl"),
+    _T ("fileno"),
+    _T ("flock"),
+    _T ("fork"),
+    _T ("formline"),
+    _T ("getc"),
+    _T ("getlogin"),
+    _T ("getpeername"),
+    _T ("getpgrp"),
+    _T ("getppid"),
+    _T ("getpriority"),
+    _T ("getpwnam"),
+    _T ("getgrname"),
+    _T ("gethostbyname"),
+    _T ("getnetbyname"),
+    _T ("getprotobyname"),
+    _T ("getpwuid"),
+    _T ("getgrgid"),
+    _T ("getservbyname"),
+    _T ("gethostbyaddr"),
+    _T ("getnetbyaddr"),
+    _T ("getprotobynumber"),
+    _T ("getservbyport"),
+    _T ("getpwent"),
+    _T ("getgrent"),
+    _T ("gethostent"),
+    _T ("getnetent"),
+    _T ("getprotoent"),
+    _T ("getservent"),
+    _T ("setpwent"),
+    _T ("setgrent"),
+    _T ("sethostent"),
+    _T ("setnetent"),
+    _T ("setprotoent"),
+    _T ("setservent"),
+    _T ("endpwent"),
+    _T ("endgrent"),
+    _T ("endhostent"),
+    _T ("endnetent"),
+    _T ("endprotoent"),
+    _T ("endservent"),
+    _T ("getsockname"),
+    _T ("getsockopt"),
+    _T ("glob"),
+    _T ("gmtime"),
+    _T ("goto"),
+    _T ("grep"),
+    _T ("hex"),
+    _T ("import"),
+    _T ("index"),
+    _T ("int"),
+    _T ("ioctl"),
+    _T ("join"),
+    _T ("keys"),
+    _T ("kill"),
+    _T ("last"),
+    _T ("lc"),
+    _T ("lcfirst"),
+    _T ("length"),
+    _T ("link"),
+    _T ("listen"),
+    _T ("local"),
+    _T ("localtime"),
+    _T ("log"),
+    _T ("lstat"),
+    _T ("map"),
+    _T ("mkdir"),
+    _T ("msgctl"),
+    _T ("msgget"),
+    _T ("msgsnd"),
+    _T ("msgrcv"),
+    _T ("my"),
+    _T ("next"),
+    _T ("no"),
+    _T ("oct"),
+    _T ("open"),
+    _T ("opendir"),
+    _T ("ord"),
+    _T ("pack"),
+    _T ("pipe"),
+    _T ("pop"),
+    _T ("pos"),
+    _T ("print"),
+    _T ("printf"),
+    _T ("push"),
+    _T ("quotemeta"),
+    _T ("rand"),
+    _T ("read"),
+    _T ("readdir"),
+    _T ("readlink"),
+    _T ("recv"),
+    _T ("redo"),
+    _T ("ref"),
+    _T ("rename"),
+    _T ("require"),
+    _T ("reset"),
+    _T ("return"),
+    _T ("reverse"),
+    _T ("rewinddir"),
+    _T ("rindex"),
+    _T ("rmdir"),
+    _T ("scalar"),
+    _T ("seek"),
+    _T ("seekdir"),
+    _T ("select"),
+    _T ("semctl"),
+    _T ("semget"),
+    _T ("semop"),
+    _T ("send"),
+    _T ("setpgrp"),
+    _T ("setpriority"),
+    _T ("setsockopt"),
+    _T ("shift"),
+    _T ("shmctl"),
+    _T ("sgmget"),
+    _T ("shmread"),
+    _T ("shmwrite"),
+    _T ("shutdown"),
+    _T ("sin"),
+    _T ("sleep"),
+    _T ("socket"),
+    _T ("socketpair"),
+    _T ("sort"),
+    _T ("splice"),
+    _T ("split"),
+    _T ("sprintf"),
+    _T ("sqrt"),
+    _T ("srand"),
+    _T ("stat"),
+    _T ("study"),
+    _T ("substr"),
+    _T ("symlink"),
+    _T ("syscall"),
+    _T ("sysread"),
+    _T ("system"),
+    _T ("syswrite"),
+    _T ("tell"),
+    _T ("telldir"),
+    _T ("tie"),
+    _T ("time"),
+    _T ("times"),
+    _T ("truncate"),
+    _T ("uc"),
+    _T ("ucfirst"),
+    _T ("umask"),
+    _T ("undef"),
+    _T ("unlink"),
+    _T ("unpack"),
+    _T ("untie"),
+    _T ("unshift"),
+    _T ("use"),
+    _T ("utime"),
+    _T ("values"),
+    _T ("vec"),
+    _T ("wait"),
+    _T ("waitpid"),
+    _T ("wantarray"),
+    _T ("warn"),
+    _T ("write"),
+    _T ("x"),
+    _T ("continue"),
+    _T ("package"),
+    _T ("bootstrap"),
+    _T ("getgrnam"),
+    _T ("tan"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsPerlKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszPerlKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsPerlNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLinePerl (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      if (pszChars[I] == '#')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsPerlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsPerlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsPerlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsPerlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/php.cpp b/Src/editlib/php.cpp
new file mode 100644 (file)
index 0000000..bbca768
--- /dev/null
@@ -0,0 +1,937 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    php.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  HTML syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszHtmlKeywordList[] =
+  {
+    // HTML section
+    _T ("DOCTYPE"),
+    _T ("PUBLIC"),
+    _T ("FRAME"),
+    _T ("FRAMESET"),
+    _T ("NOFRAMES"),
+    // HEAD section
+    _T ("HEAD"),
+    _T ("TITLE"),
+    _T ("ISINDEX"),
+    _T ("META"),
+    _T ("LINK"),
+    _T ("BASE"),
+    _T ("SCRIPT"),
+    _T ("STYLE"),
+    // BODY section
+    _T ("BODY"),
+    // headings
+    _T ("H1"),
+    _T ("H2"),
+    _T ("H3"),
+    _T ("H4"),
+    _T ("H5"),
+    _T ("H6"),
+    // lists
+    _T ("UL"),
+    _T ("OL"),
+    _T ("DIR"),
+    _T ("MENU"),
+    _T ("LI"),
+    _T ("DL"),
+    _T ("DT"),
+    _T ("DD"),
+    // text containers
+    _T ("P"),
+    _T ("PRE"),
+    _T ("BLOCKQUOTE"),
+    _T ("ADDRESS"),
+    // others
+    _T ("DIV"),
+    _T ("SPAN"),
+    _T ("CENTER"),
+    _T ("HR"),
+    _T ("FORM"),
+    _T ("TABLE"),
+    _T ("LEFT"),
+    _T ("RIGHT"),
+    _T ("TOP"),
+    // logical markup
+    _T ("EM"),
+    _T ("STRONG"),
+    _T ("DFN"),
+    _T ("CODE"),
+    _T ("SAMP"),
+    _T ("KBD"),
+    _T ("VAR"),
+    _T ("CITE"),
+    // physical markup
+    _T ("TT"),
+    _T ("I"),
+    _T ("B"),
+    _T ("U"),
+    _T ("STRIKE"),
+    _T ("BIG"),
+    _T ("SMALL"),
+    _T ("SUB"),
+    _T ("SUP"),
+    // special markup
+    _T ("A"),
+    _T ("BASEFONT"),
+    _T ("IMG"),
+    _T ("APPLET"),
+    _T ("PARAM"),
+    _T ("FONT"),
+    _T ("BR"),
+    _T ("MAP"),
+    _T ("AREA"),
+    // forms
+    _T ("INPUT"),
+    _T ("SELECT"),
+    _T ("OPTION"),
+    _T ("TEXTAREA"),
+    _T ("ONCLICK"),
+    // tables
+    _T ("CAPTION"),
+    _T ("TR"),
+    _T ("TH"),
+    _T ("TD"),
+    _T ("HTML"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("ACTION"),
+    _T ("ALIGN"),
+    _T ("ALINK"),
+    _T ("BACKGROUND"),
+    _T ("BGCOLOR"),
+    _T ("COLOR"),
+    _T ("COMPACT"),
+    _T ("CONTENT"),
+    _T ("ENCTYPE"),
+    _T ("FACE"),
+    _T ("HEIGHT"),
+    _T ("HREF"),
+    _T ("HTTP-EQUIV"),
+    _T ("LINK"),
+    _T ("METHOD"),
+    _T ("NAME"),
+    _T ("PROMPT"),
+    _T ("REL"),
+    _T ("REV"),
+    _T ("START"),
+    _T ("TEXT"),
+    _T ("TYPE"),
+    _T ("VALUE"),
+    _T ("VLINK"),
+    _T ("WIDTH"),
+    _T ("ADD_DATE"),
+    _T ("ALT"),
+    _T ("BORDER"),
+    _T ("CELLPADDING"),
+    _T ("CELLSPACING"),
+    _T ("CHECKED"),
+    _T ("CLEAR"),
+    _T ("CODE"),
+    _T ("CODEBASE"),
+    _T ("COLS"),
+    _T ("COLSPAN"),
+    _T ("COORDS"),
+    _T ("FOLDED"),
+    _T ("HSPACE"),
+    _T ("ISMAP"),
+    _T ("LAST_MODIFIED"),
+    _T ("LAST_VISIT"),
+    _T ("MAXLENGTH"),
+    _T ("MULTIPLE"),
+    _T ("NORESIZE"),
+    _T ("NOSHADE"),
+    _T ("NOWRAP"),
+    _T ("ROWS"),
+    _T ("ROWSPAN"),
+    _T ("SELECTED"),
+    _T ("SHAPE"),
+    _T ("SIZE"),
+    _T ("SRC"),
+    _T ("TARGET"),
+    _T ("USEMAP"),
+    _T ("VALIGN"),
+    _T ("VSPACE"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T ("nbsp"),
+    _T ("quot"),
+    _T ("amp"),
+    _T ("lt"),
+    _T ("lt"),
+    _T ("gt"),
+    _T ("copy"),
+    _T ("reg"),
+    _T ("acute"),
+    _T ("laquo"),
+    _T ("raquo"),
+    _T ("iexcl"),
+    _T ("iquest"),
+    _T ("Agrave"),
+    _T ("agrave"),
+    _T ("Aacute"),
+    _T ("aacute"),
+    _T ("Acirc"),
+    _T ("acirc"),
+    _T ("Atilde"),
+    _T ("atilde"),
+    _T ("Auml"),
+    _T ("auml"),
+    _T ("Aring"),
+    _T ("aring"),
+    _T ("AElig"),
+    _T ("aelig"),
+    _T ("Ccedil"),
+    _T ("ccedil"),
+    _T ("ETH"),
+    _T ("eth"),
+    _T ("Egrave"),
+    _T ("egrave"),
+    _T ("Eacute"),
+    _T ("eacute"),
+    _T ("Ecirc"),
+    _T ("ecirc"),
+    _T ("Euml"),
+    _T ("euml"),
+    _T ("Igrave"),
+    _T ("igrave"),
+    _T ("Iacute"),
+    _T ("iacute"),
+    _T ("Icirc"),
+    _T ("icirc"),
+    _T ("Iuml"),
+    _T ("iuml"),
+    _T ("Ntilde"),
+    _T ("ntilde"),
+    _T ("Ograve"),
+    _T ("ograve"),
+    _T ("Oacute"),
+    _T ("oacute"),
+    _T ("Ocirc"),
+    _T ("ocirc"),
+    _T ("Otilde"),
+    _T ("otilde"),
+    _T ("Ouml"),
+    _T ("ouml"),
+    _T ("Oslash"),
+    _T ("oslash"),
+    _T ("Ugrave"),
+    _T ("ugrave"),
+    _T ("Uacute"),
+    _T ("uacute"),
+    _T ("Ucirc"),
+    _T ("ucirc"),
+    _T ("Uuml"),
+    _T ("uuml"),
+    _T ("Yacute"),
+    _T ("yacute"),
+    _T ("yuml"),
+    _T ("THORN"),
+    _T ("thorn"),
+    _T ("szlig"),
+    _T ("sect"),
+    _T ("para"),
+    _T ("micro"),
+    _T ("brvbar"),
+    _T ("plusmn"),
+    _T ("middot"),
+    _T ("uml"),
+    _T ("cedil"),
+    _T ("ordf"),
+    _T ("ordm"),
+    _T ("not"),
+    _T ("shy"),
+    _T ("macr"),
+    _T ("deg"),
+    _T ("sup1"),
+    _T ("sup2"),
+    _T ("sup3"),
+    _T ("frac14"),
+    _T ("frac12"),
+    _T ("frac34"),
+    _T ("times"),
+    _T ("divide"),
+    _T ("cent"),
+    _T ("pound"),
+    _T ("curren"),
+    _T ("yen"),
+    NULL
+  };
+
+static LPTSTR s_apszPhpKeywordList[] =
+  {
+    _T ("exit"),
+    _T ("die"),
+    _T ("old_function"),
+    _T ("function"),
+    _T ("cfunction"),
+    _T ("const"),
+    _T ("return"),
+    _T ("if"),
+    _T ("elseif"),
+    _T ("endif"),
+    _T ("else"),
+    _T ("while"),
+    _T ("endwhile"),
+    _T ("do"),
+    _T ("for"),
+    _T ("endfor"),
+    _T ("foreach"),
+    _T ("endforeach"),
+    _T ("as"),
+    _T ("switch"),
+    _T ("endswitch"),
+    _T ("case"),
+    _T ("default"),
+    _T ("break"),
+    _T ("continue"),
+    _T ("echo"),
+    _T ("print"),
+    _T ("class"),
+    _T ("extends"),
+    _T ("new"),
+    _T ("var"),
+    _T ("int"),
+    _T ("integer"),
+    _T ("real"),
+    _T ("double"),
+    _T ("float"),
+    _T ("string"),
+    _T ("array"),
+    _T ("object"),
+    _T ("bool"),
+    _T ("boolean"),
+    _T ("eval"),
+    _T ("include"),
+    _T ("require"),
+    _T ("global"),
+    _T ("isset"),
+    _T ("empty"),
+    _T ("static"),
+    _T ("unset"),
+    _T ("list"),
+    _T ("array"),
+    NULL
+  };
+
+static LPTSTR s_apszPhp1KeywordList[] =
+  {
+    _T ("OR"),
+    _T ("AND"),
+    _T ("XOR"),
+    NULL
+  };
+
+static LPTSTR s_apszPhp2KeywordList[] =
+  {
+    _T ("__LINE__"),
+    _T ("__FILE__"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsHtmlKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszHtmlKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsPhpKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszPhpKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsPhp1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszPhp1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsPhp2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszPhp2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsPhpNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+#define COOKIE_USER1            0x0020
+#define COOKIE_USER2            0x0040
+#define COOKIE_EXT_USER1        0x0080
+
+DWORD CCrystalTextView::
+ParseLinePhp (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & (COOKIE_EXT_COMMENT|COOKIE_EXT_USER1);
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~(COOKIE_EXT_COMMENT|COOKIE_EXT_USER1)) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else if (dwCookie & COOKIE_EXT_USER1)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment <!--....-->
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          if (dwCookie & COOKIE_EXT_USER1)
+            {
+              if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+                {
+                  dwCookie &= ~COOKIE_EXT_COMMENT;
+                  bRedefineBlock = TRUE;
+                }
+              bWasCommentStart = FALSE;
+            }
+          else
+            {
+              if (I > 1 && pszChars[I] == '>' && pszChars[I - 1] == '-' && pszChars[I - 2] == '-')
+                {
+                  dwCookie &= ~COOKIE_EXT_COMMENT;
+                  bRedefineBlock = TRUE;
+                }
+            }
+          continue;
+        }
+
+      if ((dwCookie & COOKIE_EXT_USER1) && I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      if ((dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '#')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Extended comment <?....?>
+      if (dwCookie & COOKIE_EXT_USER1)
+        {
+          if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+            {
+              dwCookie &= ~COOKIE_EXT_USER1;
+              bRedefineBlock = TRUE;
+              continue;
+            }
+        }
+
+      //  Normal text
+      if ((dwCookie & (COOKIE_PREPROCESSOR|COOKIE_EXT_USER1)) && pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+
+      if ((dwCookie & (COOKIE_PREPROCESSOR|COOKIE_EXT_USER1)) && pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (dwCookie & COOKIE_EXT_USER1)
+        {
+          if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+            {
+              DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+              dwCookie |= COOKIE_EXT_COMMENT;
+              bWasCommentStart = TRUE;
+              continue;
+            }
+          bWasCommentStart = FALSE;
+        }
+      else
+        {
+          if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength - 3 && pszChars[I] == '<' && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')
+            {
+              DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+              I += 3;
+              dwCookie |= COOKIE_EXT_COMMENT;
+              dwCookie &= ~COOKIE_PREPROCESSOR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (dwCookie & COOKIE_PREPROCESSOR)
+                {
+                  if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                    }
+                  else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                    }
+                  else if (IsPhpNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              else if (dwCookie & COOKIE_EXT_USER1)
+                {
+                  if (dwCookie & COOKIE_USER2)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                    }
+                  if (IsPhpKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                    }
+                  else if (IsPhp1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_OPERATOR);
+                    }
+                  else if (IsPhp2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                    }
+                  else if (IsPhpNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                    }
+                  else
+                    {
+                      bool bFunction = FALSE;
+
+                      for (int j = I; j < nLength; j++)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == '(')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                      if (bFunction)
+                        {
+                          DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                        }
+                      else
+                        {
+                          goto next;
+                        }
+                    }
+                }
+              else if (dwCookie & COOKIE_USER1)
+                {
+                  if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+next:
+              ;
+            }
+
+          //  User1 start: <?
+          if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_NORMALTEXT);
+              dwCookie |= COOKIE_EXT_USER1;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor start: < or bracket
+          if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-'))
+            {
+              DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  User1 end: ?>
+          if (dwCookie & COOKIE_EXT_USER1)
+            {
+              if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+                {
+                  dwCookie &= ~COOKIE_EXT_USER1;
+                  nIdentBegin = -1;
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  continue;
+                }
+            }
+
+          //  Preprocessor end: > or bracket
+          if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              if (pszChars[I] == '>')
+                {
+                  dwCookie &= ~COOKIE_PREPROCESSOR;
+                  nIdentBegin = -1;
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  continue;
+                }
+            }
+
+          //  Preprocessor start: &
+          if (!(dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '&')
+            {
+              dwCookie |= COOKIE_USER1;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor end: ;
+          if (dwCookie & COOKIE_USER1)
+            {
+              if (pszChars[I] == ';')
+                {
+                  dwCookie &= ~COOKIE_USER1;
+                  nIdentBegin = -1;
+                  continue;
+                }
+            }
+
+          //  Preprocessor start: $
+          if ((dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '$')
+            {
+              dwCookie |= COOKIE_USER2;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor end: ...
+          if (dwCookie & COOKIE_USER2)
+            {
+              if (!xisalnum (pszChars[I]))
+                {
+                  dwCookie &= ~COOKIE_USER2;
+                  nIdentBegin = -1;
+                  continue;
+                }
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0 && (dwCookie & COOKIE_PREPROCESSOR))
+    {
+      if (IsHtmlKeyword (pszChars + nIdentBegin, I - nIdentBegin) && (pszChars[nIdentBegin - 1] == _T ('<') || pszChars[nIdentBegin - 1] == _T ('/')))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsPhpNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+  else if (nIdentBegin >= 0 && (dwCookie & COOKIE_EXT_USER1))
+    {
+      if (IsPhpKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsPhp1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_OPERATOR);
+        }
+      else if (IsPhp2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsPhpNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  //  User1 start: <?
+  if (I < nLength && pszChars[I] == '<' && I < nLength - 1 && (pszChars[I + 1] == '?' || pszChars[I + 1] == '%'))
+    {
+      DEFINE_BLOCK (I, COLORINDEX_NORMALTEXT);
+      dwCookie |= COOKIE_EXT_USER1;
+      nIdentBegin = -1;
+      goto end;
+    }
+
+  //  Preprocessor start: < or {
+  if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength && pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-'))
+    {
+      DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+      dwCookie |= COOKIE_PREPROCESSOR;
+      nIdentBegin = -1;
+      goto end;
+    }
+
+  //  User1 end: ?>
+  if (dwCookie & COOKIE_EXT_USER1)
+    {
+      if (I > 0 && pszChars[I] == '>' && (pszChars[I - 1] == '?' || pszChars[I - 1] == '%'))
+        {
+          dwCookie &= ~COOKIE_EXT_USER1;
+          nIdentBegin = -1;
+        }
+    }
+
+  //  Preprocessor end: > or }
+  if (dwCookie & COOKIE_PREPROCESSOR)
+    {
+      if (pszChars[I] == '>')
+        {
+          dwCookie &= ~COOKIE_PREPROCESSOR;
+          nIdentBegin = -1;
+        }
+    }
+
+end:
+  dwCookie &= (COOKIE_EXT_COMMENT | COOKIE_STRING | COOKIE_PREPROCESSOR | COOKIE_EXT_USER1);
+  return dwCookie;
+}
diff --git a/Src/editlib/python.cpp b/Src/editlib/python.cpp
new file mode 100644 (file)
index 0000000..4e5f3ff
--- /dev/null
@@ -0,0 +1,440 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    python.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Python syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszPythonKeywordList[] =
+  {
+    _T ("access"),
+    _T ("and"),
+    _T ("break"),
+    _T ("class"),
+    _T ("continue"),
+    _T ("def"),
+    _T ("del"),
+    _T ("elif"),
+    _T ("else"),
+    _T ("except"),
+    _T ("exec"),
+    _T ("finally"),
+    _T ("for"),
+    _T ("from"),
+    _T ("global"),
+    _T ("if"),
+    _T ("import"),
+    _T ("in"),
+    _T ("is"),
+    _T ("lambda"),
+    _T ("not"),
+    _T ("or"),
+    _T ("pass"),
+    _T ("print"),
+    _T ("raise"),
+    _T ("return"),
+    _T ("try"),
+    _T ("while"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("argv"),
+    _T ("builtin_module_names"),
+    _T ("exc_type"),
+    _T ("exc_value"),
+    _T ("exc_traceback"),
+    _T ("exit"),
+    _T ("exitfunc"),
+    _T ("last_type"),
+    _T ("last_value"),
+    _T ("last_traceback"),
+    _T ("modules"),
+    _T ("path"),
+    _T ("ps1"),
+    _T ("ps2"),
+    _T ("settrace"),
+    _T ("setprofile"),
+    _T ("stdin"),
+    _T ("stdout"),
+    _T ("stderr"),
+    _T ("tracebacklimit"),
+    _T ("AttributeError"),
+    _T ("EOFError"),
+    _T ("IOError"),
+    _T ("ImportError"),
+    _T ("IndexError"),
+    _T ("KeyError"),
+    _T ("KeyboardInterrupt"),
+    _T ("MemoryError"),
+    _T ("NameError"),
+    _T ("OverflowError"),
+    _T ("RuntimeError"),
+    _T ("SyntaxError"),
+    _T ("SystemError"),
+    _T ("SystemExit"),
+    _T ("TypeError"),
+    _T ("ValueError"),
+    _T ("ZeroDivisionError"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T ("id"),
+    _T ("__init__"),
+    _T ("__del__"),
+    _T ("__repr__"),
+    _T ("__str__"),
+    _T ("__cmp__"),
+    _T ("__hash__"),
+    _T ("__dict__"),
+    _T ("__methods__"),
+    _T ("__members__"),
+    _T ("__class__"),
+    _T ("__bases__"),
+    _T ("__add__"),
+    _T ("__mul__"),
+    _T ("__mod__"),
+    _T ("__sub__"),
+    _T ("__div__"),
+    _T ("divmod"),
+    _T ("__divmod__"),
+    _T ("pow"),
+    _T ("__pow__"),
+    _T ("__and__"),
+    _T ("__xor__"),
+    _T ("__or__"),
+    _T ("__lshift__"),
+    _T ("__rshift__"),
+    _T ("nonzero"),
+    _T ("__nonzero__"),
+    _T ("coerce"),
+    _T ("__coerce__"),
+    _T ("__neg__"),
+    _T ("__pos__"),
+    _T ("abs"),
+    _T ("__abs__"),
+    _T ("__invert__"),
+    _T ("int"),
+    _T ("__int__"),
+    _T ("float"),
+    _T ("__float__"),
+    _T ("long"),
+    _T ("__long__"),
+    _T ("float"),
+    _T ("__float__"),
+    _T ("oct"),
+    _T ("__oct__"),
+    _T ("hex"),
+    _T ("__hex__"),
+    _T ("range"),
+    _T ("round"),
+    _T ("xrange"),
+    _T ("len"),
+    _T ("__len__"),
+    _T ("__getitem__"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsncmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsPythonKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszPythonKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsPythonNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLinePython (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      if (pszChars[I] == '#')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsPythonKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                }
+              else if (IsPythonNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsPythonKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsPythonNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/registry.cpp b/Src/editlib/registry.cpp
new file mode 100644 (file)
index 0000000..0f7be81
--- /dev/null
@@ -0,0 +1,1463 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    registry.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Some handy stuff to deal with Windows registry
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////
+//  14-Sep-99
+//  + FIX: closing null handle (Michael A. Barnhart)
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "registry.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#pragma warning ( disable : 4711 )
+/*////////////////////////////////////////////////////////////////////////////*/
+
+/* initializes registry value data */
+void
+RegValInit (RegVal *pValData)
+{
+  ASSERT (pValData);
+  pValData->dwType = REG_NONE;
+}
+
+/* frees registry value data */
+void
+RegValFree (RegVal *pValData)
+{
+  ASSERT (pValData);
+  if (pValData->dwType == REG_SZ || pValData->dwType == REG_EXPAND_SZ
+        || pValData->dwType == REG_LINK || pValData->dwType == REG_MULTI_SZ
+        || pValData->dwType == REG_BINARY)
+    {
+      free (pValData->pbyteData);
+      pValData->dwType = REG_NONE;
+    }
+}
+
+/* get a number */
+bool
+RegValGetNumber (const RegVal *pValData, DWORD *pdwNumber)
+{
+  ASSERT (pValData &&pdwNumber);
+  if (pValData->dwType == REG_DWORD)
+    {
+      *pdwNumber = pValData->dwNumber;
+      return true;
+    }
+  return false;
+}
+
+/* get binary data */
+bool
+RegValGetBinary (const RegVal *pValData, LPBYTE pbyteData, DWORD dwSize)
+{
+  ASSERT (pValData &&pbyteData);
+  if (pValData->dwType == REG_BINARY &&dwSize >= pValData->dwSize)
+    {
+      memcpy (pbyteData, pValData->pbyteData, pValData->dwSize);
+      return true;
+    }
+  return false;
+}
+
+/* get new binary data */
+bool
+RegValGetNewBinary (const RegVal *pValData, LPBYTE *pbyteData, DWORD *pdwSize)
+{
+  ASSERT (pValData &&pbyteData);
+  if (pValData->dwType == REG_BINARY)
+    {
+      LPBYTE pbyteNewData = (LPBYTE) malloc (pValData->dwSize);
+      if (pbyteNewData)
+        {
+          *pbyteData = pbyteNewData;
+          *pdwSize = pValData->dwSize;
+          memcpy (pbyteNewData, pValData->pbyteData, pValData->dwSize);
+          return true;
+        }
+    }
+  return false;
+}
+
+/* get a new string */
+bool
+RegValGetNewString (const RegVal *pValData, LPTSTR *pszString, DWORD *pdwLength)
+{
+  ASSERT (pValData &&pszString);
+  if (pValData->dwType == REG_SZ || pValData->dwType == REG_EXPAND_SZ
+        || pValData->dwType == REG_LINK || pValData->dwType == REG_MULTI_SZ)
+    {
+      LPTSTR pszNewString = (LPTSTR) malloc (pValData->dwLength + 1);
+      if (pszNewString)
+        {
+          *pszString = pszNewString;
+          if (pdwLength)
+            {
+              *pdwLength = pValData->dwLength;
+            }
+          memcpy (pszNewString, pValData->pszString, pValData->dwLength);
+          pszNewString [pValData->dwLength] = _T ('\0');
+          return true;
+        }
+    }
+  return false;
+}
+
+/* get a string */
+bool
+RegValGetString (const RegVal *pValData, LPTSTR pszString, DWORD dwLength)
+{
+  ASSERT (pValData &&pszString);
+  if ((pValData->dwType == REG_SZ || pValData->dwType == REG_EXPAND_SZ
+         || pValData->dwType == REG_LINK || pValData->dwType == REG_MULTI_SZ)
+        && dwLength >= pValData->dwLength)
+    {
+      memcpy (pszString, pValData->pszString, pValData->dwLength);
+      pszString [pValData->dwLength] = _T ('\0');
+      return true;
+    }
+  return false;
+}
+
+/* get an array of strings */
+bool
+RegValGetStringArr (const RegVal *pValData, LPTSTR pszStrings[], DWORD dwCount)
+{
+  ASSERT (pValData);
+  if (pValData->dwType == REG_MULTI_SZ)
+    {
+      LPCTSTR pszString;
+      DWORD dwRealCount = 0, dwLength;
+      for (pszString = pValData->pszString; *pszString; pszString += dwLength)
+        {
+          dwLength = _tcslen (pszString) + 1;
+          dwRealCount++;
+        }
+      if (dwCount >= dwRealCount)
+        {
+          LPTSTR *pszDstString = pszStrings;
+          for (LPCTSTR pszString = pValData->pszString; *pszString; pszString += dwLength, pszDstString++)
+            {
+              dwLength = _tcslen (pszString) + 1;
+              LPTSTR pszNewString = (LPTSTR) malloc (dwLength);
+              *pszDstString = pszNewString;
+              if (pszNewString)
+                {
+                  while ((*pszNewString = (BYTE) *pszString) != _T ('\0'))
+                    {
+                      pszNewString++;
+                      pszString++;
+                    }
+                }
+              else
+                {
+                  while (*pszString)
+                    {
+                      pszString++;
+                    }
+                }
+            }
+          return true;
+        }
+    }
+  return false;
+}
+
+/* get a new array of strings */
+bool
+RegValGetNewStringArr (const RegVal *pValData, LPTSTR **pszStrings, DWORD *pdwCount)
+{
+  ASSERT (pValData);
+  if (pValData->dwType == REG_MULTI_SZ)
+    {
+      LPTSTR pszString;
+      DWORD dwRealCount = 0, dwLength;
+      for (pszString = pValData->pszString; *pszString; pszString += dwLength)
+        {
+          dwLength = _tcslen (pszString) + 1;
+          dwRealCount++;
+        }
+      LPTSTR *pszNewStrings = (LPTSTR *) malloc (dwRealCount *sizeof (LPTSTR));
+      if (pszNewStrings)
+        {
+          *pszStrings = pszNewStrings;
+          *pdwCount = dwRealCount;
+          for (pszString = pValData->pszString; *pszString; pszString += dwLength, pszNewStrings++)
+            {
+              dwLength = _tcslen (pszString) + 1;
+              LPTSTR pszNewString = (LPTSTR) malloc (dwLength);
+              *pszNewStrings = pszNewString;
+              if (pszNewString)
+                {
+                  while ((*pszNewString = (BYTE) *pszString) != _T ('\0'))
+                    {
+                      pszNewString++;
+                      pszString++;
+                    }
+                }
+              else
+                {
+                  while (*pszString)
+                    {
+                      pszString++;
+                    }
+                }
+            }
+          return true;
+        }
+    }
+  return false;
+}
+
+#ifdef REG_WITH_MFC
+
+/* get a string */
+bool
+RegValGetString (const RegVal *pValData, CString &sString)
+{
+  ASSERT (pValData);
+  if (pValData->dwType == REG_SZ || pValData->dwType == REG_EXPAND_SZ
+        || pValData->dwType == REG_LINK || pValData->dwType == REG_MULTI_SZ)
+    {
+      LPTSTR pszString = sString.GetBuffer (pValData->dwLength + 1);
+      memcpy (pszString, pValData->pszString, pValData->dwLength);
+      pszString [pValData->dwLength] = _T ('\0');
+      sString.ReleaseBuffer ();
+      return true;
+    }
+  return false;
+}
+
+/* get an array of strings */
+bool
+RegValGetStringArr (const RegVal *pValData, CStringArray &arrString)
+{
+  ASSERT (pValData);
+  if (pValData->dwType == REG_MULTI_SZ)
+    {
+      arrString.RemoveAll ();
+      for (LPCTSTR pszString = pValData->pszString; *pszString; pszString += _tcslen (pszString) + 1)
+        {
+          arrString.Add (pszString);
+        }
+      return true;
+    }
+  return false;
+}
+
+#endif /* REG_WITH_MFC */
+
+/* set a number */
+void
+RegValSetNumber (RegVal *pValData, DWORD dwNumber)
+{
+  ASSERT (pValData);
+  pValData->dwType = REG_DWORD;
+  pValData->dwNumber = dwNumber;
+}
+
+/* set binary data */
+bool
+RegValSetBinary (RegVal *pValData, const LPBYTE pbyteData, DWORD dwSize)
+{
+  ASSERT (pValData &&pbyteData);
+  pValData->pbyteData = (LPBYTE) malloc (dwSize);
+  if (pValData->pbyteData)
+    {
+      pValData->dwSize = dwSize;
+      pValData->dwType = REG_BINARY;
+      memcpy (pValData->pbyteData, pbyteData, dwSize);
+      return true;
+    }
+  pValData->dwType = REG_NONE;
+  return false;
+}
+
+/* set a string */
+bool
+RegValSetString (RegVal *pValData, LPCTSTR pszString)
+{
+  ASSERT (pValData &&pszString);
+  DWORD dwLength = _tcslen (pszString) + 1;
+  pValData->pszString = (LPTSTR) malloc (dwLength);
+  if (pValData->pszString)
+    {
+      pValData->dwLength = dwLength;
+      pValData->dwType = REG_SZ;
+      memcpy (pValData->pbyteData, pszString, dwLength);
+      return true;
+    }
+  pValData->dwType = REG_NONE;
+  return false;
+}
+
+bool
+RegValSetStringArr (RegVal *pValData, const LPCTSTR pszStrings[], DWORD dwCount)
+{
+  ASSERT (pValData &&pszStrings);
+  DWORD i, dwSize = 1;
+  if (dwCount)
+    {
+      for (i = 0; i < dwCount; i++)
+        {
+          dwSize += _tcslen (pszStrings[i]) + 1;
+        }
+    }
+  else
+    {
+      dwSize++;
+    }
+  pValData->pbyteData = (LPBYTE) malloc (dwSize);
+  if (pValData->pbyteData)
+    {
+      pValData->dwSize = dwSize;
+      pValData->dwType = REG_MULTI_SZ;
+      LPBYTE pbyteData = pValData->pbyteData;
+      if (dwCount)
+        {
+          for (i = 0; i < dwCount; i++)
+            {
+              LPCTSTR pszString = pszStrings[i];
+              while ((*pbyteData++ = (BYTE) *pszString) != _T ('\0'))
+                {
+                  pszString++;
+                }
+            }
+        }
+      else
+        {
+          *pbyteData++ = _T ('\0');
+        }
+      *pbyteData = _T ('\0');
+      return true;
+    }
+  pValData->dwType = REG_NONE;
+  return false;
+}
+
+#ifdef REG_WITH_MFC
+
+/* set an array of strings */
+bool
+RegValSetStringArr (RegVal *pValData, const CStringArray &arrString)
+{
+  ASSERT (pValData);
+  DWORD i, dwSize = 1, dwCount = arrString.GetSize ();
+  if (dwCount)
+    {
+      for (i = 0; i < dwCount; i++)
+        {
+          dwSize += arrString[i].GetLength () + 1;
+        }
+    }
+  else
+    {
+      dwSize++;
+    }
+  pValData->pbyteData = (LPBYTE) malloc (dwSize);
+  if (pValData->pbyteData)
+    {
+      pValData->dwSize = dwSize;
+      pValData->dwType = REG_MULTI_SZ;
+      LPBYTE pbyteData = pValData->pbyteData;
+      if (dwCount)
+        {
+          for (i = 0; i < dwCount; i++)
+            {
+              LPCTSTR pszString = arrString[i];
+              while ((*pbyteData++ = (BYTE) *pszString) != _T ('\0'))
+                {
+                  pszString++;
+                }
+            }
+        }
+      else
+        {
+          *pbyteData++ = _T ('\0');
+        }
+      *pbyteData = _T ('\0');
+      return true;
+    }
+  pValData->dwType = REG_NONE;
+  return false;
+}
+
+#endif /* REG_WITH_MFC */
+
+/* connect to remote computer registry */
+HKEY
+RegConnect (HKEY hKey, LPCTSTR pszRemote)
+{
+  HKEY hSubKey;
+  if (RegConnectRegistry (pszRemote, hKey, &hSubKey) == ERROR_SUCCESS)
+    {
+      return hSubKey;
+    }
+  return NULL;
+}
+
+/* open computer registry */
+HKEY
+RegOpen (HKEY hKey, LPCTSTR pszSubKey, DWORD dwRights)
+{
+  HKEY hSubKey;
+  if (RegOpenKeyEx (hKey, pszSubKey, 0, dwRights, &hSubKey) == ERROR_SUCCESS)
+    {
+      return hSubKey;
+    }
+  return NULL;
+}
+
+/* create computer registry */
+HKEY
+RegCreate (HKEY hKey, LPCTSTR pszSubKey, DWORD dwRights)
+{
+  HKEY hSubKey;
+  DWORD dwDisposition;
+  if (RegCreateKeyEx (hKey, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, dwRights,
+                        NULL, &hSubKey, &dwDisposition) == ERROR_SUCCESS)
+    {
+      return hSubKey;
+    }
+  return NULL;
+}
+
+/* close computer registry */
+void
+RegClose (HKEY hKey)
+{
+  if (hKey)
+    RegCloseKey (hKey);
+}
+
+/* load data of any type */
+bool
+RegLoadVal (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, RegVal *pValData)
+{
+  ASSERT (pValData);
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      DWORD dwType, dwSize;
+      if (RegQueryValueEx (hSubKey, pszValName, 0, &dwType, NULL, &dwSize) == ERROR_SUCCESS)
+        {
+          if (dwType == REG_DWORD)
+            {
+              ASSERT (dwSize == sizeof (DWORD));
+              DWORD dwNumber;
+              if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, (LPBYTE) &dwNumber, &dwSize) == ERROR_SUCCESS)
+                {
+                  ASSERT (dwSize == sizeof (DWORD));
+                  RegValFree (pValData);
+                  pValData->dwType = dwType;
+                  pValData->dwNumber = dwNumber;
+                  if (hSubKey != hKey)
+                    RegClose (hSubKey);
+                  return true;
+                }
+            }
+          else if (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_LINK
+                || dwType == REG_MULTI_SZ || dwType == REG_BINARY)
+            {
+              LPBYTE pbyteData = (LPBYTE) malloc (dwSize);
+              if (pbyteData)
+                {
+                  if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, pbyteData, &dwSize) == ERROR_SUCCESS)
+                    {
+                      RegValFree (pValData);
+                      pValData->dwType = dwType;
+                      pValData->pbyteData = pbyteData;
+                      pValData->dwLength = dwSize;
+                      if (hSubKey != hKey)
+                        RegClose (hSubKey);
+                      return true;
+                    }
+                  free (pbyteData);
+                }
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* load a number */
+bool
+RegLoadNumber (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD *pdwNumber)
+{
+  ASSERT (pdwNumber);
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      DWORD dwType, dwSize;
+      if (RegQueryValueEx (hSubKey, pszValName, 0, &dwType, NULL, &dwSize) == ERROR_SUCCESS)
+        {
+          if (dwType == REG_DWORD)
+            {
+              ASSERT (dwSize == sizeof (DWORD));
+              if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, (LPBYTE) pdwNumber, &dwSize) == ERROR_SUCCESS)
+                {
+                  ASSERT (dwSize == sizeof (DWORD));
+                  if (hSubKey != hKey)
+                    RegClose (hSubKey);
+                  return true;
+                }
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* load binary data */
+bool
+RegLoadBinary (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE pbyteData, DWORD dwSize)
+{
+  ASSERT (pbyteData);
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      DWORD dwType, dwRealSize;
+      if (RegQueryValueEx (hSubKey, pszValName, 0, &dwType, NULL, &dwRealSize) == ERROR_SUCCESS)
+        {
+          if (dwType == REG_BINARY &&dwSize >= dwRealSize)
+            {
+              if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, pbyteData, &dwRealSize) == ERROR_SUCCESS)
+                {
+                  if (hSubKey != hKey)
+                    RegClose (hSubKey);
+                  return true;
+                }
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* load new binary data */
+bool
+RegLoadNewBinary (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE *pbyteData, DWORD *pdwSize)
+{
+  ASSERT (pbyteData);
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      DWORD dwType, dwRealSize;
+      if (RegQueryValueEx (hSubKey, pszValName, 0, &dwType, NULL, &dwRealSize) == ERROR_SUCCESS)
+        {
+          if (dwType == REG_BINARY)
+            {
+              LPBYTE pbyteNewData = (LPBYTE) malloc (dwRealSize);
+              if (pbyteNewData)
+                {
+                  if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, pbyteNewData, &dwRealSize) == ERROR_SUCCESS)
+                    {
+                      *pbyteData = pbyteNewData;
+                      *pdwSize = dwRealSize;
+                      if (hSubKey != hKey)
+                        RegClose (hSubKey);
+                      return true;
+                    }
+                  free (pbyteNewData);
+                }
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* load a string */
+bool
+RegLoadString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszString, DWORD dwLength)
+{
+  ASSERT (pszString);
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      DWORD dwType, dwRealLength;
+      if (RegQueryValueEx (hSubKey, pszValName, 0, &dwType, NULL, &dwRealLength) == ERROR_SUCCESS)
+        {
+          if ((dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_LINK
+                 || dwType == REG_MULTI_SZ) &&dwLength >= dwRealLength)
+            {
+              if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, (LPBYTE) pszString, &dwRealLength) == ERROR_SUCCESS)
+                {
+                  if (hSubKey != hKey)
+                    RegClose (hSubKey);
+                  return true;
+                }
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* load a new string */
+bool
+RegLoadNewString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR *pszString, DWORD *pdwLength)
+{
+  ASSERT (pszString);
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      DWORD dwType, dwRealLength;
+      if (RegQueryValueEx (hSubKey, pszValName, 0, &dwType, NULL, &dwRealLength) == ERROR_SUCCESS)
+        {
+          if (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_LINK
+                || dwType == REG_MULTI_SZ)
+            {
+              LPTSTR pszNewString = (LPTSTR) malloc (dwRealLength);
+              if (pszNewString)
+                {
+                  if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, (LPBYTE) pszNewString, &dwRealLength) == ERROR_SUCCESS)
+                    {
+                      *pszString = pszNewString;
+                      if (pdwLength)
+                        {
+                          *pdwLength = dwRealLength;
+                        }
+                      if (hSubKey != hKey)
+                        RegClose (hSubKey);
+                      return true;
+                    }
+                  free (pszNewString);
+                }
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* load an array of strings */
+bool
+RegLoadStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszStrings[], DWORD dwCount)
+{
+  RegVal Value;
+  if (RegLoadVal (hKey, pszSubKey, pszValName, &Value))
+    {
+      if (RegValGetStringArr (&Value, pszStrings, dwCount))
+        {
+          RegValFree (&Value);
+          return true;
+        }
+      RegValFree (&Value);
+    }
+  return false;
+}
+
+/* load a new array of strings */
+bool
+RegLoadNewStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR **pszStrings, DWORD *pdwCount)
+{
+  RegVal Value;
+  if (RegLoadVal (hKey, pszSubKey, pszValName, &Value))
+    {
+      if (RegValGetNewStringArr (&Value, pszStrings, pdwCount))
+        {
+          RegValFree (&Value);
+          return true;
+        }
+      RegValFree (&Value);
+    }
+  return false;
+}
+
+#ifdef REG_WITH_MFC
+
+/* load a string */
+bool
+RegLoadString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, CString &sString)
+{
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      DWORD dwType, dwRealLength;
+      if (RegQueryValueEx (hSubKey, pszValName, 0, &dwType, NULL, &dwRealLength) == ERROR_SUCCESS)
+        {
+          if (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_LINK
+                || dwType == REG_MULTI_SZ)
+            {
+              LPTSTR pszString = sString.GetBuffer (dwRealLength);
+              if (RegQueryValueEx (hSubKey, pszValName, 0, NULL, (LPBYTE) pszString, &dwRealLength) == ERROR_SUCCESS)
+                {
+                  sString.ReleaseBuffer (dwRealLength);
+                  if (hSubKey != hKey)
+                    RegClose (hSubKey);
+                  return true;
+                }
+              sString.ReleaseBuffer (0);
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* load an array of strings */
+bool
+RegLoadStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, CStringArray &arrString)
+{
+  RegVal Value;
+  if (RegLoadVal (hKey, pszSubKey, pszValName, &Value))
+    {
+      if (RegValGetStringArr (&Value, arrString))
+        {
+          RegValFree (&Value);
+          return true;
+        }
+      RegValFree (&Value);
+    }
+  return false;
+}
+
+#endif /* REG_WITH_MFC */
+
+/* store data of any type */
+bool
+RegSaveVal (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const RegVal *pValData)
+{
+  ASSERT (pValData);
+  HKEY hSubKey = pszSubKey ? RegCreate (hKey, pszSubKey, KEY_WRITE) : hKey;
+  if (hSubKey)
+    {
+      LONG lResult;
+      if (pValData->dwType == REG_DWORD)
+        {
+          lResult = RegSetValueEx (hSubKey, pszValName, 0, pValData->dwType, (LPBYTE) &pValData->dwNumber, sizeof (DWORD));
+        }
+      else if (pValData->dwType == REG_SZ || pValData->dwType == REG_EXPAND_SZ
+            || pValData->dwType == REG_LINK || pValData->dwType == REG_MULTI_SZ
+            || pValData->dwType == REG_BINARY)
+        {
+          lResult = RegSetValueEx (hSubKey, pszValName, 0, pValData->dwType, pValData->pbyteData, pValData->dwSize);
+        }
+      else
+        {
+          lResult = ERROR_BAD_FORMAT;
+        }
+      if (lResult == ERROR_SUCCESS)
+        {
+          if (hSubKey != hKey)
+            RegClose (hSubKey);
+          return true;
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* store a number */
+bool
+RegSaveNumber (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD dwNumber)
+{
+  HKEY hSubKey = pszSubKey ? RegCreate (hKey, pszSubKey, KEY_WRITE) : hKey;
+  if (hSubKey)
+    {
+      if (RegSetValueEx (hSubKey, pszValName, 0, REG_DWORD, (LPBYTE) &dwNumber, sizeof (DWORD)) == ERROR_SUCCESS)
+        {
+          if (hSubKey != hKey)
+            RegClose (hSubKey);
+          return true;
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* store binary data */
+bool
+RegSaveBinary (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const LPBYTE pbyteData, DWORD dwSize)
+{
+  HKEY hSubKey = pszSubKey ? RegCreate (hKey, pszSubKey, KEY_WRITE) : hKey;
+  if (hSubKey)
+    {
+      if (RegSetValueEx (hSubKey, pszValName, 0, REG_BINARY, pbyteData, dwSize) == ERROR_SUCCESS)
+        {
+          if (hSubKey != hKey)
+            RegClose (hSubKey);
+          return true;
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* store a string */
+bool
+RegSaveString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPCTSTR pszString)
+{
+  HKEY hSubKey = pszSubKey ? RegCreate (hKey, pszSubKey, KEY_WRITE) : hKey;
+  if (hSubKey)
+    {
+      if (RegSetValueEx (hSubKey, pszValName, 0, REG_SZ, (LPBYTE) pszString, _tcslen (pszString) + 1) == ERROR_SUCCESS)
+        {
+          if (hSubKey != hKey)
+            RegClose (hSubKey);
+          return true;
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* store an array of strings */
+bool
+RegSaveStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const LPCTSTR pszStrings[], DWORD dwCount)
+{
+  RegVal Value;
+  if (RegValSetStringArr (&Value, pszStrings, dwCount))
+    {
+      if (RegSaveVal (hKey, pszSubKey, pszValName, &Value))
+        {
+          RegValFree (&Value);
+          return true;
+        }
+      RegValFree (&Value);
+    }
+  return false;
+}
+
+#ifdef REG_WITH_MFC
+
+/* store an array of strings */
+bool
+RegSaveStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const CStringArray &arrString)
+{
+  RegVal Value;
+  if (RegValSetStringArr (&Value, arrString))
+    {
+      if (RegSaveVal (hKey, pszSubKey, pszValName, &Value))
+        {
+          RegValFree (&Value);
+          return true;
+        }
+      RegValFree (&Value);
+    }
+  return false;
+}
+
+#endif /* REG_WITH_MFC */
+
+/* delete all subkeys in the given key */
+bool
+RegDeleteSubKeys (HKEY hKey)
+{
+  DWORD dwSubKeyCnt, dwMaxSubKey;
+  if (RegQueryInfoKey (hKey, NULL, NULL, 0, &dwSubKeyCnt, &dwMaxSubKey,
+                         NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+    {
+      if (dwSubKeyCnt)
+        {
+          LPTSTR pszKeyName = (LPTSTR) malloc (dwMaxSubKey += 1);
+          if (pszKeyName)
+            {
+              do
+                {
+                  if (RegEnumKey (hKey, --dwSubKeyCnt, pszKeyName, dwMaxSubKey) == ERROR_SUCCESS)
+                    {
+                      HKEY hSubKey = RegOpen (hKey, pszKeyName, KEY_READ | KEY_WRITE);
+                      if (hSubKey)
+                        {
+                          if (RegDeleteSubKeys (hSubKey))
+                            {
+                              RegClose (hSubKey);
+                              if (RegDeleteKey (hKey, pszKeyName) != ERROR_SUCCESS)
+                                {
+                                  free (pszKeyName);
+                                  return false;
+                                }
+                            }
+                          else
+                            {
+                              RegClose (hSubKey);
+                              free (pszKeyName);
+                              return false;
+                            }
+                        }
+                      else
+                        {
+                          free (pszKeyName);
+                          return false;
+                        }
+                    }
+                  else
+                    {
+                      free (pszKeyName);
+                      return false;
+                    }
+                }
+              while (dwSubKeyCnt);
+              free (pszKeyName);
+            }
+          else
+            {
+              return false;
+            }
+        }
+      return true;
+    }
+  return false;
+}
+
+/* delete the given value or key in the registry with all of its subkeys */
+bool
+RegDeleteKey (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName)
+{
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ | KEY_WRITE) : hKey;
+  if (hSubKey)
+    {
+      if (pszValName)
+        {
+          if (RegDeleteValue (hSubKey, pszValName) == ERROR_SUCCESS)
+            {
+              if (hSubKey != hKey)
+                RegClose (hSubKey);
+              return true;
+            }
+        }
+      else
+        {
+          if (RegDeleteSubKeys (hSubKey))
+            {
+              if (hSubKey != hKey)
+                RegClose (hSubKey);
+              return RegDeleteKey (hKey, pszSubKey) == ERROR_SUCCESS;
+            }
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  return false;
+}
+
+/* check wether the given key has other subkeys and/or values */
+bool
+RegHasEntries (HKEY hKey, LPCTSTR pszSubKey, DWORD *pdwSubKeyCount, DWORD *pdwValueCount)
+{
+  HKEY hSubKey = pszSubKey ? RegOpen (hKey, pszSubKey, KEY_READ) : hKey;
+  if (hSubKey)
+    {
+      if (RegQueryInfoKey (hSubKey, NULL, NULL, 0, pdwSubKeyCount, NULL, NULL, pdwValueCount, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+        {
+          if (hSubKey != hKey)
+            RegClose (hSubKey);
+          return true;
+        }
+      if (hSubKey != hKey)
+        RegClose (hSubKey);
+    }
+  *pdwSubKeyCount = *pdwValueCount = 0;
+  return false;
+}
+
+static LPTSTR g_pszValue = NULL;
+static DWORD g_dwValueCnt, g_dwValue, g_dwValueMax;
+
+bool RegFindFirstValue (HKEY hKey, LPCTSTR *ppszValue, RegVal *pValData);
+
+/* walks to the first value */
+bool
+RegFindFirstValue (HKEY hKey, LPCTSTR *ppszValue, RegVal *pValData)
+{
+  if (RegQueryInfoKey (hKey, NULL, NULL, 0, NULL, NULL, NULL,
+    &g_dwValueCnt, &g_dwValueMax, NULL, NULL, NULL) == ERROR_SUCCESS)
+    {
+      if (g_dwValueCnt)
+        {
+          if (g_pszValue)
+            {
+              free (g_pszValue);
+              g_pszValue = NULL;
+            }
+          g_pszValue = (LPTSTR) malloc (g_dwValueMax += 1);
+          if (g_pszValue)
+            {
+              DWORD dwMaxValue = g_dwValueMax;
+              g_dwValue = 0;
+              if (RegEnumValue (hKey, g_dwValue++, g_pszValue, &dwMaxValue, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
+                {
+                  *ppszValue = g_pszValue;
+                  return RegLoadVal (hKey, NULL, g_pszValue, pValData);
+                }
+            }
+        }
+    }
+  return false;
+}
+
+/* walks to the next value */
+bool RegFindNextValue (HKEY hKey, LPCTSTR *ppszValue, RegVal *pValData)
+{
+  DWORD dwMaxValue = g_dwValueMax;
+  if (g_dwValue < g_dwValueCnt && RegEnumValue (hKey, g_dwValue++, g_pszValue, &dwMaxValue, 0, NULL, NULL, NULL) == ERROR_SUCCESS)
+    {
+      *ppszValue = g_pszValue;
+      return RegLoadVal (hKey, NULL, g_pszValue, pValData);
+    }
+  return false;
+}
+
+/* closes registry walking */
+void RegFindClose ()
+{
+  if (g_pszValue)
+    {
+      free (g_pszValue);
+      g_pszValue = NULL;
+    }
+}
+
+/*////////////////////////////////////////////////////////////////////////////*/
+
+#ifdef __cplusplus
+
+/* constructor - automatically initializes registry value data */
+CRegVal::CRegVal ()
+{
+  Init ();
+}
+
+/* destructor - automatically frees registry value data */
+CRegVal::~CRegVal ()
+{
+  Free ();
+}
+
+/* initializes registry value data */
+void CRegVal::Init ()
+{
+  RegValInit (this);
+}
+
+/* frees registry value data */
+void CRegVal::Free ()
+{
+  RegValFree (this);
+}
+
+/* get a number */
+bool CRegVal::GetNumber (DWORD *pdwNumber) const
+{
+  return RegValGetNumber (this, pdwNumber);
+}
+
+/* get binary data */
+bool CRegVal::GetBinary (LPBYTE pbyteData, DWORD dwSize) const
+{
+  return RegValGetBinary (this, pbyteData, dwSize);
+}
+
+/* get new binary data */
+bool CRegVal::GetNewBinary (LPBYTE *pbyteData, DWORD *pdwSize) const
+{
+  return RegValGetNewBinary (this, pbyteData, pdwSize);
+}
+
+/* get a string */
+bool CRegVal::GetString (LPTSTR pszString, DWORD dwLength) const
+{
+  return RegValGetString (this, pszString, dwLength);
+}
+
+/* get a new string */
+bool CRegVal::GetNewString (LPTSTR *pszString, DWORD *pdwLength) const
+{
+  return RegValGetNewString (this, pszString, pdwLength);
+}
+
+/* get an array of strings */
+bool CRegVal::GetStringArr (LPTSTR pszStrings[], DWORD dwCount) const
+{
+  return RegValGetStringArr (this, pszStrings, dwCount);
+}
+
+/* get a new array of strings */
+bool CRegVal::GetNewStringArr (LPTSTR **pszStrings, DWORD *pdwCount) const
+{
+  return RegValGetNewStringArr (this, pszStrings, pdwCount);
+}
+
+#ifdef REG_WITH_MFC
+
+/* get a string */
+bool CRegVal::GetString (CString &sString) const
+{
+  return RegValGetString (this, sString);
+}
+
+/* get an array of strings */
+bool CRegVal::GetStringArr (CStringArray &arrString) const
+{
+  return RegValGetStringArr (this, arrString);
+}
+
+#endif /* REG_WITH_MFC */
+
+/* set a number */
+void CRegVal::SetNumber (DWORD dwNumber)
+{
+  RegValSetNumber (this, dwNumber);
+}
+
+/* set binary data */
+bool CRegVal::SetBinary (const LPBYTE pbyteData, DWORD dwSize)
+{
+  return RegValSetBinary (this, pbyteData, dwSize);
+}
+
+/* set a string */
+bool CRegVal::SetString (LPCTSTR pszString)
+{
+  return RegValSetString (this, pszString);
+}
+
+/* set an array of strings */
+bool CRegVal::SetStringArr (const LPCTSTR pszStrings[], DWORD dwCount)
+{
+  return RegValSetStringArr (this, pszStrings, dwCount);
+}
+
+#ifdef REG_WITH_MFC
+
+/* set an array of strings */
+bool CRegVal::SetStringArr (const CStringArray &arrString)
+{
+  return RegValSetStringArr (this, arrString);
+}
+
+#endif /* REG_WITH_MFC */
+
+/* constructor - automatically initializes registry data */
+CReg::CReg ()
+{
+  Open ();
+}
+
+/* destructor - automatically frees registry data */
+CReg::~CReg ()
+{
+  Close ();
+}
+
+/* connect to remote computer registry */
+HKEY CReg::Connect (HKEY hNewKey, LPCTSTR pszRemote)
+{
+  return hKey = RegConnect (hNewKey, pszRemote);
+}
+
+/* connect to registry key */
+HKEY CReg::Open (HKEY hNewKey /*= NULL*/)
+{
+  return hKey = hNewKey;
+}
+
+/* open computer registry */
+HKEY CReg::Open (HKEY hNewKey, LPCTSTR pszSubKey, DWORD dwRights)
+{
+  return hKey = RegOpen (hNewKey, pszSubKey, dwRights);
+}
+
+/* close computer registry */
+void CReg::Close ()
+{
+  if (hKey != NULL) // MAB 8 Nov 1999 - added NULL test
+    {
+      RegClose (hKey);
+      //*** MIPO 07-12-1999 - After Closing the Key, hKey must by NULL ****
+      // RegClose - dont do that - it must be done manualy
+      hKey = NULL;
+    }
+}
+
+/* create computer registry */
+HKEY CReg::Create (HKEY hNewKey, LPCTSTR pszSubKey, DWORD dwRights)
+{
+  return hKey = RegCreate (hNewKey, pszSubKey, dwRights);
+}
+
+/* load data of any type */
+bool CReg::LoadVal (LPCTSTR pszValName, RegVal *pValData)
+{
+  return RegLoadVal (hKey, NULL, pszValName, pValData);
+}
+
+/* load data of any type from subkey */
+bool CReg::LoadVal (LPCTSTR pszSubKey, LPCTSTR pszValName, RegVal *pValData)
+{
+  return RegLoadVal (hKey, pszSubKey, pszValName, pValData);
+}
+
+/* load a number */
+bool CReg::LoadNumber (LPCTSTR pszValName, DWORD *pdwNumber)
+{
+  return RegLoadNumber (hKey, NULL, pszValName, pdwNumber);
+}
+
+/* load a number from subkey */
+bool CReg::LoadNumber (LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD *pdwNumber)
+{
+  return RegLoadNumber (hKey, pszSubKey, pszValName, pdwNumber);
+}
+
+/* load binary data */
+bool CReg::LoadBinary (LPCTSTR pszValName, LPBYTE pbyteData, DWORD dwSize)
+{
+  return RegLoadBinary (hKey, NULL, pszValName, pbyteData, dwSize);
+}
+
+/* load binary data from subkey */
+bool CReg::LoadBinary (LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE pbyteData, DWORD dwSize)
+{
+  return RegLoadBinary (hKey, pszSubKey, pszValName, pbyteData, dwSize);
+}
+
+/* load new binary data */
+bool CReg::LoadNewBinary (LPCTSTR pszValName, LPBYTE *pbyteData, DWORD *pdwSize)
+{
+  return RegLoadNewBinary (hKey, NULL, pszValName, pbyteData, pdwSize);
+}
+
+/* load new binary data from subkey */
+bool CReg::LoadNewBinary (LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE *pbyteData, DWORD *pdwSize)
+{
+  return RegLoadNewBinary (hKey, pszSubKey, pszValName, pbyteData, pdwSize);
+}
+
+/* load a string */
+bool CReg::LoadString (LPCTSTR pszValName, LPTSTR pszString, DWORD dwLength)
+{
+  return RegLoadString (hKey, NULL, pszValName, pszString, dwLength);
+}
+
+/* load a string from subkey */
+bool CReg::LoadString (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszString, DWORD dwLength)
+{
+  return RegLoadString (hKey, pszSubKey, pszValName, pszString, dwLength);
+}
+
+/* load a new string */
+bool CReg::LoadNewString (LPCTSTR pszValName, LPTSTR *pszString, DWORD *pdwLength)
+{
+  return RegLoadNewString (hKey, NULL, pszValName, pszString, pdwLength);
+}
+
+/* load a new string from subkey */
+bool CReg::LoadNewString (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR *pszString, DWORD *pdwLength)
+{
+  return RegLoadNewString (hKey, pszSubKey, pszValName, pszString, pdwLength);
+}
+
+/* load an array of strings */
+bool CReg::LoadStringArr (LPCTSTR pszValName, LPTSTR pszStrings[], DWORD dwCount)
+{
+  return RegLoadStringArr (hKey, NULL, pszValName, pszStrings, dwCount);
+}
+
+/* load an array of strings from subkey */
+bool CReg::LoadStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszStrings[], DWORD dwCount)
+{
+  return RegLoadStringArr (hKey, pszSubKey, pszValName, pszStrings, dwCount);
+}
+
+/* load a new array of strings */
+bool CReg::LoadNewStringArr (LPCTSTR pszValName, LPTSTR **pszStrings, DWORD *pdwCount)
+{
+  return RegLoadNewStringArr (hKey, NULL, pszValName, pszStrings, pdwCount);
+}
+
+/* load a new array of strings from subkey */
+bool CReg::LoadNewStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR **pszStrings, DWORD *pdwCount)
+{
+  return RegLoadNewStringArr (hKey, pszSubKey, pszValName, pszStrings, pdwCount);
+}
+
+#ifdef REG_WITH_MFC
+
+/* load a string */
+bool CReg::LoadString (LPCTSTR pszValName, CString &sString)
+{
+  return RegLoadString (hKey, NULL, pszValName, sString);
+}
+
+/* load a string from subkey */
+bool CReg::LoadString (LPCTSTR pszSubKey, LPCTSTR pszValName, CString &sString)
+{
+  return RegLoadString (hKey, pszSubKey, pszValName, sString);
+}
+
+/* load an array of strings */
+bool CReg::LoadStringArr (LPCTSTR pszValName, CStringArray &arrString)
+{
+  return RegLoadStringArr (hKey, NULL, pszValName, arrString);
+}
+
+/* load an array of strings from subkey */
+bool CReg::LoadStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, CStringArray &arrString)
+{
+  return RegLoadStringArr (hKey, pszSubKey, pszValName, arrString);
+}
+
+#endif /* REG_WITH_MFC */
+
+/* store data of any type */
+bool CReg::SaveVal (LPCTSTR pszValName, const RegVal *pValData)
+{
+  return RegSaveVal (hKey, NULL, pszValName, pValData);
+}
+
+/* store data of any type to subkey */
+bool CReg::SaveVal (LPCTSTR pszSubKey, LPCTSTR pszValName, const RegVal *pValData)
+{
+  return RegSaveVal (hKey, pszSubKey, pszValName, pValData);
+}
+
+/* store a number */
+bool CReg::SaveNumber (LPCTSTR pszValName, DWORD dwNumber)
+{
+  return RegSaveNumber (hKey, NULL, pszValName, dwNumber);
+}
+
+/* store a number to subkey */
+bool CReg::SaveNumber (LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD dwNumber)
+{
+  return RegSaveNumber (hKey, pszSubKey, pszValName, dwNumber);
+}
+
+/* store binary data */
+bool CReg::SaveBinary (LPCTSTR pszValName, const LPBYTE pbyteData, DWORD dwSize)
+{
+  return RegSaveBinary (hKey, NULL, pszValName, pbyteData, dwSize);
+}
+
+/* store binary data to subkey */
+bool CReg::SaveBinary (LPCTSTR pszSubKey, LPCTSTR pszValName, const LPBYTE pbyteData, DWORD dwSize)
+{
+  return RegSaveBinary (hKey, pszSubKey, pszValName, pbyteData, dwSize);
+}
+
+/* store a string */
+bool CReg::SaveString (LPCTSTR pszValName, LPCTSTR pszString)
+{
+  return RegSaveString (hKey, NULL, pszValName, pszString);
+}
+
+/* store a string to subkey */
+bool CReg::SaveString (LPCTSTR pszSubKey, LPCTSTR pszValName, LPCTSTR pszString)
+{
+  return RegSaveString (hKey, pszSubKey, pszValName, pszString);
+}
+
+/* store an array of strings */
+bool CReg::SaveStringArr (LPCTSTR pszValName, const LPCTSTR pszStrings[], DWORD dwCount)
+{
+  return RegSaveStringArr (hKey, NULL, pszValName, pszStrings, dwCount);
+}
+
+/* store an array of strings to subkey */
+bool CReg::SaveStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, const LPCTSTR pszStrings[], DWORD dwCount)
+{
+  return RegSaveStringArr (hKey, pszSubKey, pszValName, pszStrings, dwCount);
+}
+
+#ifdef REG_WITH_MFC
+
+/* store an array of strings */
+bool CReg::SaveStringArr (LPCTSTR pszValName, const CStringArray &arrString)
+{
+  return RegSaveStringArr (hKey, NULL, pszValName, arrString);
+}
+
+/* store an array of strings to subkey */
+bool CReg::SaveStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, const CStringArray &arrString)
+{
+  return RegSaveStringArr (hKey, pszSubKey, pszValName, arrString);
+}
+
+#endif /* REG_WITH_MFC */
+
+/* delete the given value or key in the registry with all of its subkeys */
+bool CReg::DeleteKey (LPCTSTR pszValName)
+{
+  return RegDeleteKey (hKey, NULL, pszValName);
+}
+
+/* delete the given value or key in the registry with all of its subkeys in subkey */
+bool CReg::DeleteKey (LPCTSTR pszSubKey, LPCTSTR pszValName)
+{
+  return RegDeleteKey (hKey, pszSubKey, pszValName);
+}
+
+/* delete all of subkeys in the key */
+bool CReg::DeleteSubKeys ()
+{
+  return RegDeleteSubKeys (hKey);
+}
+
+/* check wether the given key has other subkeys and/or values */
+bool CReg::HasEntries (DWORD *pdwSubKeyCount, DWORD *pdwValueCount)
+{
+  return RegHasEntries (hKey, NULL, pdwSubKeyCount, pdwValueCount);
+}
+
+/* check wether the given key has other subkeys and/or values in subkey */
+bool CReg::HasEntries (LPCTSTR pszSubKey, DWORD *pdwSubKeyCount, DWORD *pdwValueCount)
+{
+  return RegHasEntries (hKey, pszSubKey, pdwSubKeyCount, pdwValueCount);
+}
+
+/* walks to the first value */
+bool CReg::FindFirstValue (LPCTSTR &ppszValue, RegVal *pValData)
+{
+  return RegFindFirstValue (hKey, &ppszValue, pValData);
+}
+
+/* walks to the next value */
+bool CReg::FindNextValue (LPCTSTR &ppszValue, RegVal *pValData)
+{
+  return RegFindNextValue (hKey, &ppszValue, pValData);
+}
+
+/* closes registry walking */
+void CReg::FindClose ()
+{
+  RegFindClose ();
+}
+
+#endif /* cplusplus */
+
+/*////////////////////////////////////////////////////////////////////////////*/
+#pragma warning ( default : 4711 )
diff --git a/Src/editlib/registry.h b/Src/editlib/registry.h
new file mode 100644 (file)
index 0000000..e023dcd
--- /dev/null
@@ -0,0 +1,411 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    registry.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Some handy stuff to deal with Windows registry
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __REGISTRY_H__INCLUDED__
+#define __REGISTRY_H__INCLUDED__
+
+/*////////////////////////////////////////////////////////////////////////////*/
+
+#if (defined (__AFXWIN_H__) || defined (ARX_WITH_MFC)) && !defined (REG_WITH_MFC)
+#define REG_WITH_MFC
+#endif
+
+struct RegVal
+  {
+    DWORD dwType;
+
+    union
+      {
+        DWORD dwNumber;
+        LPBYTE pbyteData;
+        LPTSTR pszString;
+      };
+    union
+      {
+        DWORD dwSize;
+        DWORD dwLength;
+      };
+  };
+
+/* initializes registry value data */
+void EDITPADC_CLASS RegValInit (RegVal *pValData);
+
+/* frees registry value data */
+void EDITPADC_CLASS RegValFree (RegVal *pValData);
+
+/* get a number */
+bool EDITPADC_CLASS RegValGetNumber (const RegVal *pValData, DWORD *pdwNumber);
+
+/* get binary data */
+bool EDITPADC_CLASS RegValGetBinary (const RegVal *pValData, LPBYTE pbyteData, DWORD dwSize);
+
+/* get new binary data */
+bool EDITPADC_CLASS RegValGetNewBinary (const RegVal *pValData, LPBYTE *pbyteData, DWORD *pdwSize);
+
+/* get a string */
+bool EDITPADC_CLASS RegValGetString (const RegVal *pValData, LPTSTR pszString, DWORD dwLength);
+
+/* get a new string */
+bool EDITPADC_CLASS RegValGetNewString (const RegVal *pValData, LPTSTR *pszString, DWORD *pdwLength);
+
+/* get an array of strings */
+bool EDITPADC_CLASS RegValGetStringArr (const RegVal *pValData, LPTSTR pszStrings[], DWORD dwCount);
+
+/* get a new array of strings */
+bool EDITPADC_CLASS RegValGetNewStringArr (const RegVal *pValData, LPTSTR **pszStrings, DWORD *pdwCount);
+
+#ifdef REG_WITH_MFC
+
+/* get a string */
+bool EDITPADC_CLASS RegValGetString (const RegVal *pValData, CString &sString);
+
+/* get an array of strings */
+bool EDITPADC_CLASS RegValGetStringArr (const RegVal *pValData, CStringArray &arrString);
+
+#endif /* REG_WITH_MFC */
+
+/* set a number */
+void EDITPADC_CLASS RegValSetNumber (RegVal *pValData, DWORD dwNumber);
+
+/* set binary data */
+bool EDITPADC_CLASS RegValSetBinary (RegVal *pValData, const LPBYTE pbyteData, DWORD dwSize);
+
+/* set a string */
+bool EDITPADC_CLASS RegValSetString (RegVal *pValData, LPCTSTR pszString);
+
+/* set an array of strings */
+bool EDITPADC_CLASS RegValSetStringArr (RegVal *pValData, const LPCTSTR pszStrings[], DWORD dwCount);
+
+#ifdef REG_WITH_MFC
+
+/* set an array of strings */
+bool EDITPADC_CLASS RegValSetStringArr (RegVal *pValData, const CStringArray &arrString);
+
+#endif /* REG_WITH_MFC */
+
+/* connect to remote computer registry */
+HKEY EDITPADC_CLASS RegConnect (HKEY hKey, LPCTSTR pszRemote);
+
+/* open computer registry */
+HKEY EDITPADC_CLASS RegOpen (HKEY hKey, LPCTSTR pszSubKey, DWORD dwRights);
+
+/* close computer registry */
+void EDITPADC_CLASS RegClose (HKEY hKey);
+
+/* create computer registry */
+HKEY EDITPADC_CLASS RegCreate (HKEY hKey, LPCTSTR pszSubKey, DWORD dwRights);
+
+/* load data of any type */
+bool EDITPADC_CLASS RegLoadVal (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, RegVal *pValData);
+
+/* load a number */
+bool EDITPADC_CLASS RegLoadNumber (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD *pdwNumber);
+
+/* load binary data */
+bool EDITPADC_CLASS RegLoadBinary (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE pbyteData, DWORD dwSize);
+
+/* load new binary data */
+bool EDITPADC_CLASS RegLoadNewBinary (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE *pbyteData, DWORD *pdwSize);
+
+/* load a string */
+bool EDITPADC_CLASS RegLoadString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszString, DWORD dwLength);
+
+/* load a new string */
+bool EDITPADC_CLASS RegLoadNewString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR *pszString, DWORD *pdwLength);
+
+/* load an array of strings */
+bool EDITPADC_CLASS RegLoadStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszStrings[], DWORD dwCount);
+
+/* load a new array of strings */
+bool EDITPADC_CLASS RegLoadNewStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR **pszStrings, DWORD *pdwCount);
+
+#ifdef REG_WITH_MFC
+
+/* load a string */
+bool EDITPADC_CLASS RegLoadString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, CString &sString);
+
+/* load an array of strings */
+bool EDITPADC_CLASS RegLoadStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, CStringArray &arrString);
+
+#endif /* REG_WITH_MFC */
+
+/* store data of any type */
+bool EDITPADC_CLASS RegSaveVal (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const RegVal *pValData);
+
+/* store a number */
+bool EDITPADC_CLASS RegSaveNumber (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD dwNumber);
+
+/* store binary data */
+bool EDITPADC_CLASS RegSaveBinary (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const LPBYTE pbyteData, DWORD dwSize);
+
+/* store a string */
+bool EDITPADC_CLASS RegSaveString (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, LPCTSTR pszString);
+
+/* store an array of strings */
+bool EDITPADC_CLASS RegSaveStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const LPCTSTR pszStrings[], DWORD dwCount);
+
+#ifdef REG_WITH_MFC
+
+/* store an array of strings */
+bool EDITPADC_CLASS RegSaveStringArr (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName, const CStringArray &arrString);
+
+#endif /* REG_WITH_MFC */
+
+/* delete the given value or key in the registry with all of its subkeys */
+bool EDITPADC_CLASS RegDeleteKey (HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValName);
+
+/* check wether the given key has other subkeys and/or values */
+bool EDITPADC_CLASS RegHasEntries (HKEY hKey, LPCTSTR pszSubKey, DWORD *pdwSubKeyCount, DWORD *pdwValueCount);
+
+/* walks to the first value */
+bool RegFindFirstValue (HKEY hKey, LPCTSTR *ppszValue, RegVal *pValData);
+
+/* walks to the next value */
+bool RegFindNextValue (HKEY hKey, LPCTSTR *ppszValue, RegVal *pValData);
+
+/* closes registry walking */
+void RegFindClose ();
+
+/*////////////////////////////////////////////////////////////////////////////*/
+
+#ifdef __cplusplus
+
+struct EDITPADC_CLASS CRegVal : public RegVal
+  {
+    /* constructor - automatically initializes registry value data */
+    CRegVal ();
+
+    /* destructor - automatically frees registry value data */
+    ~CRegVal ();
+    
+    /* initializes registry value data */
+    void Init ();
+    
+    /* frees registry value data */
+    void Free ();
+    
+    /* get a number */
+    bool GetNumber (DWORD *pdwNumber) const;
+    
+    /* get binary data */
+    bool GetBinary (LPBYTE pbyteData, DWORD dwSize) const;
+    
+    /* get new binary data */
+    bool GetNewBinary (LPBYTE *pbyteData, DWORD *pdwSize) const;
+    
+    /* get a string */
+    bool GetString (LPTSTR pszString, DWORD dwLength) const;
+    
+    /* get a new string */
+    bool GetNewString (LPTSTR *pszString, DWORD *pdwLength) const;
+    
+    /* get an array of strings */
+    bool GetStringArr (LPTSTR pszStrings[], DWORD dwCount) const;
+    
+    /* get a new array of strings */
+    bool GetNewStringArr (LPTSTR **pszStrings, DWORD *pdwCount) const;
+    
+    #ifdef REG_WITH_MFC
+    
+    /* get a string */
+    bool GetString (CString &sString) const;
+    
+    /* get an array of strings */
+    bool GetStringArr (CStringArray &arrString) const;
+    
+    #endif /* REG_WITH_MFC */
+    
+    /* set a number */
+    void SetNumber (DWORD dwNumber);
+    
+    /* set binary data */
+    bool SetBinary (const LPBYTE pbyteData, DWORD dwSize);
+    
+    /* set a string */
+    bool SetString (LPCTSTR pszString);
+    
+    /* set an array of strings */
+    bool SetStringArr (const LPCTSTR pszStrings[], DWORD dwCount);
+    
+    #ifdef REG_WITH_MFC
+    
+    /* set an array of strings */
+    bool SetStringArr (const CStringArray &arrString);
+    
+    #endif /* REG_WITH_MFC */
+  };
+
+struct EDITPADC_CLASS CReg
+  {
+    HKEY hKey;
+    
+    /* constructor - automatically initializes registry data */
+    CReg ();
+
+    /* destructor - automatically frees registry data */
+    ~CReg ();
+    
+    /* connect to remote computer registry */
+    HKEY Connect (HKEY hNewKey, LPCTSTR pszRemote);
+    
+    /* connect to registry key */
+    HKEY Open (HKEY hNewKey = NULL);
+    
+    /* open computer registry */
+    HKEY Open (HKEY hNewKey, LPCTSTR pszSubKey, DWORD dwRights);
+    
+    /* close computer registry */
+    void Close ();
+    
+    /* create computer registry */
+    HKEY Create (HKEY hNewKey, LPCTSTR pszSubKey, DWORD dwRights);
+    
+    /* load data of any type */
+    bool LoadVal (LPCTSTR pszValName, RegVal *pValData);
+    
+    /* load data of any type from subkey */
+    bool LoadVal (LPCTSTR pszSubKey, LPCTSTR pszValName, RegVal *pValData);
+    
+    /* load a number */
+    bool LoadNumber (LPCTSTR pszValName, DWORD *pdwNumber);
+    
+    /* load a number from subkey */
+    bool LoadNumber (LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD *pdwNumber);
+    
+    /* load binary data */
+    bool LoadBinary (LPCTSTR pszValName, LPBYTE pbyteData, DWORD dwSize);
+    
+    /* load binary data from subkey */
+    bool LoadBinary (LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE pbyteData, DWORD dwSize);
+    
+    /* load new binary data */
+    bool LoadNewBinary (LPCTSTR pszValName, LPBYTE *pbyteData, DWORD *pdwSize);
+    
+    /* load new binary data from subkey */
+    bool LoadNewBinary (LPCTSTR pszSubKey, LPCTSTR pszValName, LPBYTE *pbyteData, DWORD *pdwSize);
+    
+    /* load a string */
+    bool LoadString (LPCTSTR pszValName, LPTSTR pszString, DWORD dwLength);
+    
+    /* load a string from subkey */
+    bool LoadString (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszString, DWORD dwLength);
+    
+    /* load a new string */
+    bool LoadNewString (LPCTSTR pszValName, LPTSTR *pszString, DWORD *pdwLength);
+    
+    /* load a new string from subkey */
+    bool LoadNewString (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR *pszString, DWORD *pdwLength);
+    
+    /* load an array of strings */
+    bool LoadStringArr (LPCTSTR pszValName, LPTSTR pszStrings[], DWORD dwCount);
+    
+    /* load an array of strings from subkey */
+    bool LoadStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR pszStrings[], DWORD dwCount);
+    
+    /* load a new array of strings */
+    bool LoadNewStringArr (LPCTSTR pszValName, LPTSTR **pszStrings, DWORD *pdwCount);
+    
+    /* load a new array of strings from subkey */
+    bool LoadNewStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, LPTSTR **pszStrings, DWORD *pdwCount);
+    
+    #ifdef REG_WITH_MFC
+    
+    /* load a string */
+    bool LoadString (LPCTSTR pszValName, CString &sString);
+    
+    /* load a string from subkey */
+    bool LoadString (LPCTSTR pszSubKey, LPCTSTR pszValName, CString &sString);
+    
+    /* load an array of strings */
+    bool LoadStringArr (LPCTSTR pszValName, CStringArray &arrString);
+    
+    /* load an array of strings from subkey */
+    bool LoadStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, CStringArray &arrString);
+    
+    #endif /* REG_WITH_MFC */
+    
+    /* store data of any type */
+    bool SaveVal (LPCTSTR pszValName, const RegVal *pValData);
+    
+    /* store data of any type to subkey */
+    bool SaveVal (LPCTSTR pszSubKey, LPCTSTR pszValName, const RegVal *pValData);
+    
+    /* store a number */
+    bool SaveNumber (LPCTSTR pszValName, DWORD dwNumber);
+    
+    /* store a number to subkey */
+    bool SaveNumber (LPCTSTR pszSubKey, LPCTSTR pszValName, DWORD dwNumber);
+    
+    /* store binary data */
+    bool SaveBinary (LPCTSTR pszValName, const LPBYTE pbyteData, DWORD dwSize);
+    
+    /* store binary data to subkey */
+    bool SaveBinary (LPCTSTR pszSubKey, LPCTSTR pszValName, const LPBYTE pbyteData, DWORD dwSize);
+    
+    /* store a string */
+    bool SaveString (LPCTSTR pszValName, LPCTSTR pszString);
+    
+    /* store a string to subkey */
+    bool SaveString (LPCTSTR pszSubKey, LPCTSTR pszValName, LPCTSTR pszString);
+    
+    /* store an array of strings */
+    bool SaveStringArr (LPCTSTR pszValName, const LPCTSTR pszStrings[], DWORD dwCount);
+    
+    /* store an array of strings to subkey */
+    bool SaveStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, const LPCTSTR pszStrings[], DWORD dwCount);
+    
+    #ifdef REG_WITH_MFC
+    
+    /* store an array of strings */
+    bool SaveStringArr (LPCTSTR pszValName, const CStringArray &arrString);
+    
+    /* store an array of strings to subkey */
+    bool SaveStringArr (LPCTSTR pszSubKey, LPCTSTR pszValName, const CStringArray &arrString);
+    
+    #endif /* REG_WITH_MFC */
+    
+    /* delete the given value or key in the registry with all of its subkeys */
+    bool DeleteKey (LPCTSTR pszValName);
+    
+    /* delete the given value or key in the registry with all of its subkeys in subkey */
+    bool DeleteKey (LPCTSTR pszSubKey, LPCTSTR pszValName);
+    
+    /* delete all of subkeys in the key */
+    bool DeleteSubKeys ();
+    
+    /* check wether the given key has other subkeys and/or values */
+    bool HasEntries (DWORD *pdwSubKeyCount, DWORD *pdwValueCount);
+    
+    /* check wether the given key has other subkeys and/or values in subkey */
+    bool HasEntries (LPCTSTR pszSubKey, DWORD *pdwSubKeyCount, DWORD *pdwValueCount);
+    
+    /* walks to the first value */
+    bool FindFirstValue (LPCTSTR &ppszValue, RegVal *pValData);
+    
+    /* walks to the next value */
+    bool FindNextValue (LPCTSTR &ppszValue, RegVal *pValData);
+    
+    /* closes registry walking */
+    void FindClose ();
+  };
+
+#endif /* cplusplus */
+
+bool EDITPADC_CLASS RegDeleteSubKeys (HKEY hKey);
+
+/*////////////////////////////////////////////////////////////////////////////*/
+
+#endif /* __REGISTRY_H__INCLUDED__ */
diff --git a/Src/editlib/rexx.cpp b/Src/editlib/rexx.cpp
new file mode 100644 (file)
index 0000000..9df41c5
--- /dev/null
@@ -0,0 +1,393 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    rexx.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  REXX syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszRexxKeywordList[] =
+  {
+    _T ("ADDRESS"),
+    _T ("ARG"),
+    _T ("CALL"),
+    _T ("DO"),
+    _T ("DROP"),
+    _T ("EXIT"),
+    _T ("IF"),
+    _T ("INTERPRET"),
+    _T ("ITERATE"),
+    _T ("LEAVE"),
+    _T ("NOP"),
+    _T ("NUMERIC"),
+    _T ("OPTIONS"),
+    _T ("PARSE"),
+    _T ("PROCEDURE"),
+    _T ("PULL"),
+    _T ("PUSH"),
+    _T ("QUEUE"),
+    _T ("RETURN"),
+    _T ("SAY"),
+    _T ("SELECT"),
+    _T ("OTHERWISE"),
+    _T ("SIGNAL"),
+    _T ("TRACE"),
+    _T ("END"),
+    _T ("WHEN"),
+    _T ("ELSE"),
+    _T ("WITH"),
+    _T ("TO"),
+    _T ("BY"),
+    _T ("ON"),
+    _T ("END"),
+    _T ("FOR"),
+    _T ("OFF"),
+    _T ("VAR"),
+    _T ("THEN"),
+    _T ("HALT"),
+    _T ("NAME"),
+    _T ("FORM"),
+    _T ("FUZZ"),
+    _T ("VALUE"),
+    _T ("WHILE"),
+    _T ("UNTIL"),
+    _T ("ERROR"),
+    _T ("UPPER"),
+    _T ("WITH"),
+    _T ("EXPOSE"),
+    _T ("DIGITS"),
+    _T ("FOREVER"),
+    _T ("FAILURE"),
+    _T ("VERSION"),
+    _T ("NOVALUE"),
+    _T ("SOURCE"),
+    _T ("SYNTAX"),
+    _T ("NOTREADY"),
+    _T ("SCIENTIFIC"),
+    _T ("ENGINEERING"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("METHOD"),
+    _T ("CLASS"),
+    _T ("NULL"),
+    _T ("LOOP"),
+    _T ("CATCH"),
+    _T ("RETURNS"),
+    _T ("EXTENDS"),
+    _T ("IMPLEMENTS"),
+    _T ("CHAR"),
+    _T ("BOOLEAN"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsRexxKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszRexxKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsRexxNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineRexx (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsRexxKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsRexxNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsRexxKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsRexxNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/rsrc.cpp b/Src/editlib/rsrc.cpp
new file mode 100644 (file)
index 0000000..ae7e6c7
--- /dev/null
@@ -0,0 +1,355 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    rsrc.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Windows resources syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszRsrcKeywordList[] =
+  {
+    _T ("MENU"),
+    _T ("POPUP"),
+    _T ("MENUITEM"),
+    _T ("SEPARATOR"),
+    _T ("BEGIN"),
+    _T ("END"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("VK_F1"),
+    _T ("VK_F2"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsRsrcKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszRsrcKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsRsrcNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineRsrc (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || pszChars[I - 1] != '\\'))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Preprocessor directive #....
+      if (dwCookie & COOKIE_PREPROCESSOR)
+        {
+          if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+            {
+              DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+              dwCookie |= COOKIE_EXT_COMMENT;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (pszChars[I] == '#')
+            {
+              DEFINE_BLOCK (I, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              continue;
+            }
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsRsrcKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsRsrcNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsRsrcKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsRsrcNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/sgml.cpp b/Src/editlib/sgml.cpp
new file mode 100644 (file)
index 0000000..e46a39f
--- /dev/null
@@ -0,0 +1,551 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    sgml.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  SGML syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszSgmlKeywordList[] =
+  {
+    _T ("ABSTRACT"),
+    _T ("ARTICLE"),
+    _T ("AUTHOR"),
+    _T ("BF"),
+    _T ("BOOK"),
+    _T ("CHAPT"),
+    _T ("CODE"),
+    _T ("COPYRIGHT"),
+    _T ("DATE"),
+    _T ("DEBIANDOC"),
+    _T ("DESCRIP"),
+    _T ("DOCTYPE"),
+    _T ("EM"),
+    _T ("EMAIL"),
+    _T ("ENUM"),
+    _T ("ENUMLIST"),
+    _T ("EXAMPLE"),
+    _T ("FOOTNOTE"),
+    _T ("FTPSITE"),
+    _T ("FTPPATH"),
+    _T ("HEADING"),
+    _T ("HTMLURL"),
+    _T ("HTTPSITE"),
+    _T ("HTTPPATH"),
+    _T ("IT"),
+    _T ("ITEM"),
+    _T ("ITEMIZE"),
+    _T ("LABEL"),
+    _T ("LIST"),
+    _T ("MANREF"),
+    _T ("NAME"),
+    _T ("P"),
+    _T ("PRGN"),
+    _T ("PUBLIC"),
+    _T ("QREF"),
+    _T ("QUOTE"),
+    _T ("REF"),
+    _T ("SECT"),
+    _T ("SECT1"),
+    _T ("SECT2"),
+    _T ("SECT3"),
+    _T ("SECT4"),
+    _T ("STRONG"),
+    _T ("SYSTEM"),
+    _T ("TAG"),
+    _T ("TAGLIST"),
+    _T ("TITLE"),
+    _T ("TITLEPAG"),
+    _T ("TOC"),
+    _T ("TSCREEN"),
+    _T ("TT"),
+    _T ("URL"),
+    _T ("VAR"),
+    _T ("VERB"),
+    _T ("VERSION"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("COMPACT"),
+    _T ("ID"),
+    _T ("NAME"),
+    _T ("SECTION"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T ("nbsp"),
+    _T ("quot"),
+    _T ("amp"),
+    _T ("lt"),
+    _T ("lt"),
+    _T ("gt"),
+    _T ("copy"),
+    _T ("reg"),
+    _T ("acute"),
+    _T ("laquo"),
+    _T ("raquo"),
+    _T ("iexcl"),
+    _T ("iquest"),
+    _T ("Agrave"),
+    _T ("agrave"),
+    _T ("Aacute"),
+    _T ("aacute"),
+    _T ("Acirc"),
+    _T ("acirc"),
+    _T ("Atilde"),
+    _T ("atilde"),
+    _T ("Auml"),
+    _T ("auml"),
+    _T ("Aring"),
+    _T ("aring"),
+    _T ("AElig"),
+    _T ("aelig"),
+    _T ("Ccedil"),
+    _T ("ccedil"),
+    _T ("ETH"),
+    _T ("eth"),
+    _T ("Egrave"),
+    _T ("egrave"),
+    _T ("Eacute"),
+    _T ("eacute"),
+    _T ("Ecirc"),
+    _T ("ecirc"),
+    _T ("Euml"),
+    _T ("euml"),
+    _T ("Igrave"),
+    _T ("igrave"),
+    _T ("Iacute"),
+    _T ("iacute"),
+    _T ("Icirc"),
+    _T ("icirc"),
+    _T ("Iuml"),
+    _T ("iuml"),
+    _T ("Ntilde"),
+    _T ("ntilde"),
+    _T ("Ograve"),
+    _T ("ograve"),
+    _T ("Oacute"),
+    _T ("oacute"),
+    _T ("Ocirc"),
+    _T ("ocirc"),
+    _T ("Otilde"),
+    _T ("otilde"),
+    _T ("Ouml"),
+    _T ("ouml"),
+    _T ("Oslash"),
+    _T ("oslash"),
+    _T ("Ugrave"),
+    _T ("ugrave"),
+    _T ("Uacute"),
+    _T ("uacute"),
+    _T ("Ucirc"),
+    _T ("ucirc"),
+    _T ("Uuml"),
+    _T ("uuml"),
+    _T ("Yacute"),
+    _T ("yacute"),
+    _T ("yuml"),
+    _T ("THORN"),
+    _T ("thorn"),
+    _T ("szlig"),
+    _T ("sect"),
+    _T ("para"),
+    _T ("micro"),
+    _T ("brvbar"),
+    _T ("plusmn"),
+    _T ("middot"),
+    _T ("uml"),
+    _T ("cedil"),
+    _T ("ordf"),
+    _T ("ordm"),
+    _T ("not"),
+    _T ("shy"),
+    _T ("macr"),
+    _T ("deg"),
+    _T ("sup1"),
+    _T ("sup2"),
+    _T ("sup3"),
+    _T ("frac14"),
+    _T ("frac12"),
+    _T ("frac34"),
+    _T ("times"),
+    _T ("divide"),
+    _T ("cent"),
+    _T ("pound"),
+    _T ("curren"),
+    _T ("yen"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsSgmlKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszSgmlKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsSgmlNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+#define COOKIE_USER1            0x0020
+#define COOKIE_EXT_USER1        0x0040
+
+DWORD CCrystalTextView::
+ParseLineSgml (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_PREPROCESSOR);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment <!--....-->
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          if (I > 1 && pszChars[I] == '>' && pszChars[I - 1] == '-' && pszChars[I - 2] == '-')
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment <?....?>
+      if (dwCookie & COOKIE_EXT_USER1)
+        {
+          if (I > 0 && pszChars[I] == '>' && pszChars[I - 1] == '?')
+            {
+              dwCookie &= ~COOKIE_EXT_USER1;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (!(dwCookie & COOKIE_EXT_USER1) && I < nLength - 3 && pszChars[I] == '<' && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          I += 3;
+          dwCookie |= COOKIE_EXT_COMMENT;
+          dwCookie &= ~COOKIE_PREPROCESSOR;
+          continue;
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (dwCookie & COOKIE_PREPROCESSOR)
+                {
+                  if (IsSgmlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                    }
+                  else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                    }
+                  else if (IsSgmlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              else if (dwCookie & COOKIE_USER1)
+                {
+                  if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                    }
+                  else
+                    {
+                      goto next;
+                    }
+                }
+              else if (IsSgmlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  goto next;
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+next:
+              ;
+            }
+          //  Preprocessor start: < or bracket
+          if (!(dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-') || pszChars[I] == '{')
+            {
+              DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+              dwCookie |= COOKIE_PREPROCESSOR;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor end: > or bracket
+          if (dwCookie & COOKIE_PREPROCESSOR)
+            {
+              if (pszChars[I] == '>' || pszChars[I] == '}')
+                {
+                  dwCookie &= ~COOKIE_PREPROCESSOR;
+                  nIdentBegin = -1;
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  continue;
+                }
+            }
+          //  Preprocessor start: &
+          if (pszChars[I] == '&')
+            {
+              dwCookie |= COOKIE_USER1;
+              nIdentBegin = -1;
+              continue;
+            }
+
+          //  Preprocessor end: ;
+          if (dwCookie & COOKIE_USER1)
+            {
+              if (pszChars[I] == ';')
+                {
+                  dwCookie &= ~COOKIE_USER1;
+                  nIdentBegin = -1;
+                  continue;
+                }
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0 && (dwCookie & COOKIE_PREPROCESSOR))
+    {
+      if (IsSgmlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsSgmlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+    }
+  //  Preprocessor start: < or {
+  if (!(dwCookie & COOKIE_EXT_USER1) && pszChars[I] == '<' && !(I < nLength - 3 && pszChars[I + 1] == '!' && pszChars[I + 2] == '-' && pszChars[I + 3] == '-') || pszChars[I] == '{')
+    {
+      DEFINE_BLOCK (I + 1, COLORINDEX_PREPROCESSOR);
+      dwCookie |= COOKIE_PREPROCESSOR;
+      nIdentBegin = -1;
+      goto end;
+    }
+
+  //  Preprocessor end: > or }
+  if (dwCookie & COOKIE_PREPROCESSOR)
+    {
+      if (pszChars[I] == '>' || pszChars[I] == '}')
+        {
+          dwCookie &= ~COOKIE_PREPROCESSOR;
+          nIdentBegin = -1;
+        }
+    }
+end:
+  dwCookie &= (COOKIE_EXT_COMMENT | COOKIE_STRING | COOKIE_PREPROCESSOR | COOKIE_EXT_USER1);
+  return dwCookie;
+}
diff --git a/Src/editlib/sh.cpp b/Src/editlib/sh.cpp
new file mode 100644 (file)
index 0000000..85435cb
--- /dev/null
@@ -0,0 +1,339 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    sh.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  UNIX shell script syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszShKeywordList[] =
+  {
+    _T ("case"),
+    _T ("do"),
+    _T ("done"),
+    _T ("elif"),
+    _T ("else"),
+    _T ("esac"),
+    _T ("fi"),
+    _T ("for"),
+    _T ("function"),
+    _T ("if"),
+    _T ("in"),
+    _T ("then"),
+    _T ("until"),
+    _T ("while"),
+    _T ("exec"),
+    _T ("export"),
+    _T ("set"),
+    _T ("echo"),
+    _T ("exit"),
+    _T ("select"),
+    _T ("source"),
+    _T ("unset"),
+    _T ("alias"),
+    _T ("unalias"),
+    _T ("shift"),
+    _T ("break"),
+    _T ("read"),
+    _T ("return"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("ls"),
+    _T ("pwd"),
+    _T ("chown"),
+    _T ("chmod"),
+    _T ("logout"),
+    _T ("ssh"),
+    _T ("telnet"),
+    _T ("who"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsShKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszShKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsShNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineSh (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      if (pszChars[I] == '#')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsShKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsShNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsShKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsShNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/siod.cpp b/Src/editlib/siod.cpp
new file mode 100644 (file)
index 0000000..c23a0b4
--- /dev/null
@@ -0,0 +1,670 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    siod.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  SIOD syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszSiodKeywordList[] =
+  {
+    _T("abs"),
+    _T("alarm"),
+    _T("and"),
+    _T("append"),
+    _T("apply"),
+    _T("ass"),
+    _T("assoc"),
+    _T("assq"),
+    _T("assv"),
+    _T("base64decode"),
+    _T("base64encode"),
+    _T("begin"),
+    _T("caaar"),
+    _T("caadr"),
+    _T("caar"),
+    _T("cadar"),
+    _T("caddr"),
+    _T("cadr"),
+    _T("car"),
+    _T("cdaar"),
+    _T("cdadr"),
+    _T("cdar"),
+    _T("cddar"),
+    _T("cdddr"),
+    _T("cddr"),
+    _T("cdr"),
+    _T("cond"),
+    _T("cons-array"),
+    _T("define"),
+    _T("eq?"),
+    _T("equal?"),
+    _T("eqv?"),
+    _T("eval"),
+    _T("exec"),
+    _T("exit"),
+    _T("fclose"),
+    _T("fopen"),
+    _T("if"),
+    _T("lambda"),
+    _T("length"),
+    _T("let"),
+    _T("let*"),
+    _T("letrec"),
+    _T("list"),
+    _T("load"),
+    _T("max"),
+    _T("min"),
+    _T("member"),
+    _T("memq"),
+    _T("memv"),
+    _T("nil"),
+    _T("not"),
+    _T("null?"),
+    _T("number?"),
+    _T("number->string"),
+    _T("or"),
+    _T("pair?"),
+    _T("quit"),
+    _T("quote"),
+    _T("set!"),
+    _T("set-car!"),
+    _T("set-cdr!"),
+    _T("string->number"),
+    _T("string-length"),
+    _T("string?"),
+    _T("string-append"),
+    _T("substring"),
+    _T("symbol?"),
+    _T("read"),
+    _T("reverse"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T("acos"),
+    _T("asin"),
+    _T("atan"),
+    _T("cos"),
+    _T("exp"),
+    _T("log"),
+    _T("sin"),
+    _T("tan"),
+    _T("sqrt"),
+    NULL
+  };
+
+static LPTSTR s_apszUser2KeywordList[] =
+  {
+    _T("%%%memref"),
+    _T("%%closure"),
+    _T("%%closure-code"),
+    _T("%%closure-env"),
+    _T("%%stack-limit"),
+    _T("*after-gc*"),
+    _T("*args*"),
+    _T("*catch"),
+    _T("*env*"),
+    _T("*eval-history-ptr*"),
+    _T("*pi*"),
+    _T("*plists*"),
+    _T("*throw"),
+    _T("*traced*"),
+    _T("F_GETLK"),
+    _T("F_SETLK"),
+    _T("F_SETLKW"),
+    _T("access-problem?"),
+    _T("allocate-heap"),
+    _T("apropos"),
+    _T("aref"),
+    _T("array->hexstr"),
+    _T("aset"),
+    _T("ash"),
+    _T("atan2"),
+    _T("benchmark-eval"),
+    _T("benchmark-funcall1"),
+    _T("benchmark-funcall2"),
+    _T("bit-and"),
+    _T("bit-not"),
+    _T("bit-or"),
+    _T("bit-xor"),
+    _T("butlast"),
+    _T("bytes-append"),
+    _T("chdir"),
+    _T("chmod"),
+    _T("chown"),
+    _T("closedir"),
+    _T("copy-list"),
+    _T("cpu-usage-limits"),
+    _T("crypt"),
+    _T("current-resource-usage"),
+    _T("datlength"),
+    _T("datref"),
+    _T("decode-file-mode"),
+    _T("delete-file"),
+    _T("delq"),
+    _T("encode-file-mode"),
+    _T("encode-open-flags"),
+    _T("endpwent"),
+    _T("env-lookup"),
+    _T("eof-val"),
+    _T("errobj"),
+    _T("error"),
+    _T("fast-load"),
+    _T("fast-print"),
+    _T("fast-read"),
+    _T("fast-save"),
+    _T("fchmod"),
+    _T("fflush"),
+    _T("file-times"),
+    _T("first"),
+    _T("fmod"),
+    _T("fnmatch"),
+    _T("fork"),
+    _T("fread"),
+    _T("fseek"),
+    _T("fstat"),
+    _T("ftell"),
+    _T("fwrite"),
+    _T("gc"),
+    _T("gc-info"),
+    _T("gc-status"),
+    _T("get"),
+    _T("getc"),
+    _T("getcwd"),
+    _T("getenv"),
+    _T("getgid"),
+    _T("getgrgid"),
+    _T("getpass"),
+    _T("getpgrp"),
+    _T("getpid"),
+    _T("getppid"),
+    _T("getpwent"),
+    _T("getpwnam"),
+    _T("getpwuid"),
+    _T("gets"),
+    _T("getuid"),
+    _T("gmtime"),
+    _T("hexstr->bytes"),
+    _T("href"),
+    _T("hset"),
+    _T("html-encode"),
+    _T("intern"),
+    _T("kill"),
+    _T("larg-default"),
+    _T("last"),
+    _T("last-c-error"),
+    _T("lchown"),
+    _T("link"),
+    _T("lkey-default"),
+    _T("load-so"),
+    _T("localtime"),
+    _T("lref-default"),
+    _T("lstat"),
+    _T("make-list"),
+    _T("mapcar"),
+    _T("md5-final"),
+    _T("md5-init"),
+    _T("md5-update"),
+    _T("mkdatref"),
+    _T("mkdir"),
+    _T("mktime"),
+    _T("nconc"),
+    _T("nice"),
+    _T("nreverse"),
+    _T("nth"),
+    _T("opendir"),
+    _T("os-classification"),
+    _T("parse-number"),
+    _T("pclose"),
+    _T("popen"),
+    _T("pow"),
+    _T("prin1"),
+    _T("print"),
+    _T("print-to-string"),
+    _T("prog1"),
+    _T("putc"),
+    _T("putenv"),
+    _T("putprop"),
+    _T("puts"),
+    _T("qsort"),
+    _T("rand"),
+    _T("random"),
+    _T("read-from-string"),
+    _T("readdir"),
+    _T("readline"),
+    _T("readlink"),
+    _T("realtime"),
+    _T("rename"),
+    _T("require"),
+    _T("require-so"),
+    _T("rest"),
+    _T("rld-pathnames"),
+    _T("rmdir"),
+    _T("runtime"),
+    _T("save-forms"),
+    _T("sdatref"),
+    _T("set-eval-history"),
+    _T("set-symbol-value!"),
+    _T("setprop"),
+    _T("setpwent"),
+    _T("setuid"),
+    _T("siod-lib"),
+    _T("sleep"),
+    _T("so-ext"),
+    _T("srand"),
+    _T("srandom"),
+    _T("stat"),
+    _T("strbreakup"),
+    _T("strcat"),
+    _T("strcmp"),
+    _T("strcpy"),
+    _T("strcspn"),
+    _T("strftime"),
+    _T("string-dimension"),
+    _T("string-downcase"),
+    _T("string-lessp"),
+    _T("string-search"),
+    _T("string-trim"),
+    _T("string-trim-left"),
+    _T("string-trim-right"),
+    _T("string-upcase"),
+    _T("strptime"),
+    _T("strspn"),
+    _T("subset"),
+    _T("substring-equal?"),
+    _T("swrite"),
+    _T("sxhash"),
+    _T("symbol-bound?"),
+    _T("symbol-value"),
+    _T("symbolconc"),
+    _T("symlink"),
+    _T("system"),
+    _T("t"),
+    _T("the-environment"),
+    _T("trace"),
+    _T("trunc"),
+    _T("typeof"),
+    _T("unbreakupstr"),
+    _T("ungetc"),
+    _T("unix-ctime"),
+    _T("unix-time"),
+    _T("unix-time->strtime"),
+    _T("unlink"),
+    _T("untrace"),
+    _T("url-decode"),
+    _T("url-encode"),
+    _T("utime"),
+    _T("verbose"),
+    _T("wait"),
+    _T("while"),
+    _T("writes"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsSiodKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszSiodKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser2Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser2KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsSiodNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineSiod (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  BOOL bDefun = FALSE;
+
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == ';' && pszChars[I - 1] == '|')
+          if ((I > 1 && pszChars[I] == ';' && pszChars[I - 1] == '|' /*&& pszChars[I - 2] != ';'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == ';' && pszChars[I - 1] == '|'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] != '|' && pszChars[I - 1] == ';')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '|' && pszChars[I - 1] == ';')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsSiodKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  if (!_tcsnicmp (_T ("defun"), pszChars + nIdentBegin, 5))
+                    {
+                      bDefun = TRUE;
+                    }
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+                }
+              else if (IsSiodNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  if (!bDefun)
+                    {
+                      for (int j = nIdentBegin; --j >= 0;)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == '(')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                    }
+                  if (!bFunction)
+                    {
+                      for (int j = I; j >= 0; j--)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == '(')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsSiodKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          if (!_tcsnicmp (_T ("defun"), pszChars + nIdentBegin, 5))
+            {
+              bDefun = TRUE;
+            }
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsUser2Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER2);
+        }
+      else if (IsSiodNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          if (!bDefun)
+            {
+              for (int j = nIdentBegin; --j >= 0;)
+                {
+                  if (!isspace (pszChars[j]))
+                    {
+                      if (pszChars[j] == '(')
+                        {
+                          bFunction = TRUE;
+                        }
+                      break;
+                    }
+                }
+            }
+          if (!bFunction)
+            {
+              for (int j = I; j >= 0; j--)
+                {
+                  if (!isspace (pszChars[j]))
+                    {
+                      if (pszChars[j] == '(')
+                        {
+                          bFunction = TRUE;
+                        }
+                      break;
+                    }
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/splash.cpp b/Src/editlib/splash.cpp
new file mode 100644 (file)
index 0000000..173a527
--- /dev/null
@@ -0,0 +1,116 @@
+#include "stdafx.h"
+#include "editcmd.h"
+#include "splash.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char BASED_CODE THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CSplashWnd dialog
+
+BOOL CSplashWnd::Create(CWnd* pParent)
+{
+       //{{AFX_DATA_INIT(CSplashWnd)
+               // NOTE: the ClassWizard will add member initialization here
+       //}}AFX_DATA_INIT
+
+       if (!CDialog::Create(CSplashWnd::IDD, pParent))
+       {
+               TRACE0("Warning: creation of CSplashWnd dialog failed\n");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+BOOL CSplashWnd::OnInitDialog()
+{
+       CDialog::OnInitDialog();
+       CenterWindow();
+
+       // initialize the big icon control
+       m_icon.SubclassDlgItem(IDC_BIGICON, this);
+       m_icon.SizeToContent();
+
+       return TRUE;  // return TRUE  unless you set the focus to a control
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CSplashWnd message handlers
+
+/////////////////////////////////////////////////////////////////////////////
+// CBigIcon
+
+BEGIN_MESSAGE_MAP(CBigIcon, CButton)
+       //{{AFX_MSG_MAP(CBigIcon)
+       ON_WM_DRAWITEM()
+       ON_WM_ERASEBKGND()
+       //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBigIcon message handlers
+
+#define CY_SHADOW   4
+#define CX_SHADOW   4
+
+void CBigIcon::SizeToContent()
+{
+       m_bitmap.LoadBitmap(IDB_BITMAP48);
+       BITMAP bm;
+       m_bitmap.GetObject(sizeof(bm), &bm);
+       m_sizeBitmap = CSize(bm.bmWidth, bm.bmHeight);
+       // get system icon size
+
+       // a big icon should be twice the size of an icon + shadows
+       SetWindowPos(NULL, 0, 0, bm.bmWidth + CX_SHADOW + 4, bm.bmHeight + CY_SHADOW + 4,
+               SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
+}
+
+void CBigIcon::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
+{
+       CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
+       ASSERT(pDC != NULL);
+
+       CRect rect;
+       GetClientRect(rect);
+       int cxClient = rect.Width();
+       int cyClient = rect.Height();
+
+       // draw border around icon
+       CPen pen;
+       pen.CreateStockObject(BLACK_PEN);
+       CPen* pPenOld = pDC->SelectObject(&pen);
+       pDC->Rectangle(0, 0, cxClient-CX_SHADOW, cyClient-CY_SHADOW);
+       if (pPenOld)
+               pDC->SelectObject(pPenOld);
+
+       // draw shadows around icon
+       CBrush br;
+       br.CreateStockObject(DKGRAY_BRUSH);
+       rect.SetRect(cxClient-CX_SHADOW, CY_SHADOW, cxClient, cyClient);
+       pDC->FillRect(rect, &br);
+       rect.SetRect(CX_SHADOW, cyClient-CY_SHADOW, cxClient, cyClient);
+       pDC->FillRect(rect, &br);
+
+       // draw the bitmap contents
+       CDC dcMem;
+       if (!dcMem.CreateCompatibleDC(pDC))
+               return;
+       CBitmap* pBitmapOld = dcMem.SelectObject(&m_bitmap);
+       if (pBitmapOld == NULL)
+               return;
+
+       pDC->BitBlt(2, 2, m_sizeBitmap.cx, m_sizeBitmap.cy, &dcMem, 0, 0, SRCCOPY);
+
+       dcMem.SelectObject(pBitmapOld);
+}
+
+BOOL CBigIcon::OnEraseBkgnd(CDC*)
+{
+       return TRUE;    // we don't do any erasing...
+}
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/Src/editlib/splash.h b/Src/editlib/splash.h
new file mode 100644 (file)
index 0000000..a85b214
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __SPLASH_H__INCLUDED__
+#define __SPLASH_H__INCLUDED__
+
+/////////////////////////////////////////////////////////////////////////////
+// CBigIcon window
+
+class EDITPADC_CLASS CBigIcon : public CButton
+{
+// Attributes
+public:
+       CBitmap m_bitmap;
+       CSize m_sizeBitmap;
+
+// Operations
+public:
+       void SizeToContent();
+
+// Implementation
+protected:
+       virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
+
+       //{{AFX_MSG(CBigIcon)
+       afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+       //}}AFX_MSG
+       DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CSplash dialog
+
+class EDITPADC_CLASS CSplashWnd : public CDialog
+{
+// Construction
+public:
+       BOOL Create(CWnd* pParent);
+
+// Dialog Data
+       //{{AFX_DATA(CSplashWnd)
+       enum { IDD = IDD_SPLASH };
+               // NOTE: the ClassWizard will add data members here
+       //}}AFX_DATA
+
+// Implementation
+protected:
+       CBigIcon m_icon; // self-draw button
+
+       // Generated message map functions
+       //{{AFX_MSG(CSplashWnd)
+       virtual BOOL OnInitDialog();
+       //}}AFX_MSG
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // __SPLASH_H__INCLUDED__
diff --git a/Src/editlib/sql.cpp b/Src/editlib/sql.cpp
new file mode 100644 (file)
index 0000000..13793e0
--- /dev/null
@@ -0,0 +1,353 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    sql.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  SQL syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszSqlKeywordList[] =
+  {
+    _T ("select"),
+    _T ("where"),
+    _T ("insert"),
+    _T ("into"),
+    _T ("update"),
+    _T ("from"),
+    _T ("in"),
+    _T ("order"),
+    _T ("by"),
+    _T ("and"),
+    _T ("or"),
+    _T ("not"),
+    _T ("union"),
+    _T ("distinct"),
+    _T ("join"),
+    _T ("all"),
+    _T ("group"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("CHAR"),
+    _T ("VARCHAR"),
+    _T ("INTEGER"),
+    _T ("REAL"),
+    _T ("DOUBLE"),
+    _T ("MEMO"),
+    _T ("BYTE"),
+    _T ("WORD"),
+    _T ("DATE"),
+    _T ("TIME"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsSqlKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszSqlKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsSqlNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineSql (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bWasCommentStart = FALSE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Extended comment /*....*/
+      if (dwCookie & COOKIE_EXT_COMMENT)
+        {
+          // if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '*')
+          if ((I > 1 && pszChars[I] == '/' && pszChars[I - 1] == '*' /*&& pszChars[I - 2] != '/'*/ && !bWasCommentStart) || (I == 1 && pszChars[I] == '/' && pszChars[I - 1] == '*'))
+            {
+              dwCookie &= ~COOKIE_EXT_COMMENT;
+              bRedefineBlock = TRUE;
+            }
+          bWasCommentStart = FALSE;
+          continue;
+        }
+
+      if (I > 0 && pszChars[I] == '/' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+      if (I > 0 && pszChars[I] == '*' && pszChars[I - 1] == '/')
+        {
+          DEFINE_BLOCK (I - 1, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_EXT_COMMENT;
+          bWasCommentStart = TRUE;
+          continue;
+        }
+
+      bWasCommentStart = FALSE;
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsSqlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsSqlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsSqlKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsSqlNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/statbar.cpp b/Src/editlib/statbar.cpp
new file mode 100644 (file)
index 0000000..9c25723
--- /dev/null
@@ -0,0 +1,126 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    statbar.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Status bar extension
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "editcmd.h"
+#include "statbar.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+CEditStatusBar::CEditStatusBar ()
+    :CStatusBar (), m_strClockFormat (_T("%d.%m. %H:%M:%S"))
+{
+}
+
+CEditStatusBar:: ~ CEditStatusBar ()
+{
+}
+
+BOOL CEditStatusBar::
+Create (CWnd * pParentWnd, DWORD dwStyle, UINT nID)
+{
+  BOOL bCreatedOK = CStatusBar::Create (pParentWnd, dwStyle, nID);
+  return bCreatedOK;
+}
+
+BOOL CEditStatusBar::
+SetPaneFormattedText (int nIndex, BOOL bUpdate, LPCTSTR lpszFmt,...)
+{
+  TCHAR buffer[256];
+  va_list argptr;
+  va_start (argptr, lpszFmt);
+  _vstprintf (buffer, lpszFmt, argptr);
+  va_end (argptr);
+  BOOL bResult = SetPaneText (nIndex, buffer, bUpdate);
+  UpdateWindow ();
+  return bResult;
+}
+
+BOOL CEditStatusBar::
+SetPaneFormattedText (int nIndex, BOOL bUpdate, UINT nId,...)
+{
+  CString str;
+  if (str.LoadString (nId))
+    {
+      va_list argptr;
+      va_start (argptr, nId);
+      BOOL bResult = SetPaneFormattedText (nIndex, bUpdate, str, argptr);
+      va_end (argptr);
+      return bResult;
+    }
+  SetPaneText (nIndex, _T (""), bUpdate);
+  return FALSE;
+}
+
+BOOL CEditStatusBar::
+SetPaneText (int nIndex, LPCTSTR lpszNewText, BOOL bUpdate /*= TRUE*/ )
+{
+  return CStatusBar::SetPaneText (nIndex, lpszNewText, bUpdate);
+}
+
+BOOL CEditStatusBar::
+SetPaneText (int nIndex, UINT nId, BOOL bUpdate /*= TRUE*/ )
+{
+  CString str;
+  if (str.LoadString (nId))
+    return SetPaneText (nIndex, str, bUpdate);
+  SetPaneText (nIndex, _T (""), bUpdate);
+  return FALSE;
+}
+
+void CEditStatusBar::
+SetClockFormat (LPCTSTR strClockFormat)
+{
+  m_strClockFormat = strClockFormat;
+}
+
+IMPLEMENT_DYNCREATE (CEditStatusBar, CStatusBar)
+
+BEGIN_MESSAGE_MAP (CEditStatusBar, CStatusBar)
+//{{AFX_MSG_MAP(CEditStatusBar)
+ON_WM_CREATE ()
+ON_WM_DESTROY ()
+ON_UPDATE_COMMAND_UI (ID_INDICATOR_TIME, OnUpdateIndicatorTime)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP ()
+
+int CEditStatusBar::OnCreate (LPCREATESTRUCT lpCreateStruct)
+{
+  // make sure time gets updated every second, even when idle
+  if (CStatusBar::OnCreate (lpCreateStruct) == -1)
+    return -1;
+  SetFont (CFont::FromHandle ((HFONT) GetStockObject (DEFAULT_GUI_FONT)));
+  SetTimer (ID_INDICATOR_TIME, 1000, NULL);
+  return 0;
+}
+
+void CEditStatusBar::
+OnUpdateIndicatorTime (CCmdUI * pCmdUI)
+{
+  pCmdUI->Enable (true);
+  pCmdUI->SetText (CTime::GetCurrentTime ().Format (m_strClockFormat));
+}
+
+void CEditStatusBar::
+OnDestroy ()
+{
+  KillTimer (ID_INDICATOR_TIME);
+  CStatusBar::OnDestroy ();
+}
diff --git a/Src/editlib/statbar.h b/Src/editlib/statbar.h
new file mode 100644 (file)
index 0000000..4410163
--- /dev/null
@@ -0,0 +1,53 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    statbar.h
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  Status bar extension
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __STATBAR_H__INCLUDED__
+#define __STATBAR_H__INCLUDED__
+
+class EDITPADC_CLASS CEditStatusBar : public CStatusBar
+  {
+    DECLARE_DYNCREATE (CEditStatusBar)
+public :
+    CEditStatusBar ();
+    ~CEditStatusBar ();
+    virtual BOOL Create (CWnd * pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, UINT nID = AFX_IDW_STATUS_BAR);
+
+protected :
+    CString m_strClockFormat;
+
+public :
+    BOOL SetPaneFormattedText (int nIndex, BOOL bUpdate, LPCTSTR lpszFmt,...);
+    BOOL SetPaneFormattedText (int nIndex, BOOL bUpdate, UINT nId,...);
+    BOOL SetPaneText (int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE);
+    BOOL SetPaneText (int nIndex, UINT nId, BOOL bUpdate = TRUE);
+    void SetClockFormat (LPCTSTR strClockFormat);
+
+    // Overrides
+    // ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CEditStatusBar)
+    //}}AFX_VIRTUAL
+
+    // Generated message map functions
+    //{{AFX_MSG(CEditStatusBar)
+    afx_msg void OnDestroy ();
+    afx_msg void OnUpdateIndicatorTime (CCmdUI * pCmdUI);
+    afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct);
+    //}}AFX_MSG
+
+    DECLARE_MESSAGE_MAP ()
+  };
+
+#endif // __STATBAR_H__INCLUDED__
diff --git a/Src/editlib/tcl.cpp b/Src/editlib/tcl.cpp
new file mode 100644 (file)
index 0000000..3054703
--- /dev/null
@@ -0,0 +1,298 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    tcl.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  TCL syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszTclKeywordList[] =
+  {
+    _T ("case"),
+    _T ("do"),
+    _T ("done"),
+    _T ("elif"),
+    _T ("else"),
+    _T ("esac"),
+    _T ("fi"),
+    _T ("for"),
+    _T ("function"),
+    _T ("if"),
+    _T ("in"),
+    _T ("then"),
+    _T ("until"),
+    _T ("while"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsTclKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszTclKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsTclNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineTcl (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.' && nPos > 0 && (!xisalpha (pszChars[nPos - 1]) && !xisalpha (pszChars[nPos + 1])))
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      if (pszChars[I] == '#')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.' && I > 0 && (!xisalpha (pszChars[I - 1]) && !xisalpha (pszChars[I + 1])))
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsTclKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsTclNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  for (int j = I; j < nLength; j++)
+                    {
+                      if (!isspace (pszChars[j]))
+                        {
+                          if (pszChars[j] == '(')
+                            {
+                              bFunction = TRUE;
+                            }
+                          break;
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsTclKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsTclNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          for (int j = I; j < nLength; j++)
+            {
+              if (!isspace (pszChars[j]))
+                {
+                  if (pszChars[j] == '(')
+                    {
+                      bFunction = TRUE;
+                    }
+                  break;
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  if (pszChars[nLength - 1] != '\\')
+    dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/tex.cpp b/Src/editlib/tex.cpp
new file mode 100644 (file)
index 0000000..6dc079f
--- /dev/null
@@ -0,0 +1,1133 @@
+///////////////////////////////////////////////////////////////////////////
+//  File:    tex.cpp
+//  Version: 1.1.0.4
+//  Updated: 19-Jul-1998
+//
+//  Copyright:  Ferdinand Prantl, portions by Stcherbatchenko Andrei
+//  E-mail:     prantl@ff.cuni.cz
+//
+//  TEX syntax highlighing definition
+//
+//  You are free to use or modify this code to the following restrictions:
+//  - Acknowledge me somewhere in your about box, simple "Parts of code by.."
+//  will be enough. If you can't (or don't want to), contact me personally.
+//  - LEAVE THIS HEADER INTACT
+////////////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ccrystaltextview.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//  C++ keywords (MSVC5.0 + POET5.0)
+static LPTSTR s_apszTexKeywordList[] =
+  {
+    _T ("documentstyle"),
+    _T ("document"),
+    _T ("documentclass"),
+    _T ("pagestyle"),
+    _T ("pagenumbering"),
+    _T ("thispagestyle"),
+    _T ("title"),
+    _T ("author"),
+    _T ("date"),
+    _T ("maketitle"),
+    _T ("begin"),
+    _T ("end"),
+    _T ("part"),
+    _T ("chapter"),
+    _T ("section"),
+    _T ("subsection"),
+    _T ("subsubsection"),
+    _T ("paragraph"),
+    _T ("subparagraph"),
+    _T ("appendix"),
+    _T ("tableofcontents"),
+    _T ("listoffigures"),
+    _T ("listoftables"),
+    _T ("rm"),
+    _T ("em"),
+    _T ("bf"),
+    _T ("sc"),
+    _T ("it"),
+    _T ("sl"),
+    _T ("sf"),
+    _T ("tt"),
+    _T ("tiny"),
+    _T ("scriptsize"),
+    _T ("footnotesize"),
+    _T ("small"),
+    _T ("normalsize"),
+    _T ("large"),
+    _T ("Large"),
+    _T ("LARGE"),
+    _T ("huge"),
+    _T ("HUGE"),
+    _T ("bibitem"),
+    _T ("cite"),
+    _T ("label"),
+    _T ("ref"),
+    _T ("pageref"),
+    _T ("footnote"),
+    _T ("item"),
+    _T ("caption"),
+    _T ("kill"),
+    _T ("hline"),
+    _T ("cline"),
+    _T ("multicolumn"),
+    _T ("def"),
+    _T ("hspace"),
+    _T ("vspace"),
+    _T ("linebreak"),
+    _T ("nolinebreak"),
+    _T ("newpage"),
+    _T ("clearpage"),
+    _T ("pagebreak"),
+    _T ("nopagebreak"),
+    _T ("samepage"),
+    _T ("newcommand"),
+    _T ("renewcommand"),
+    _T ("newenvironment"),
+    _T ("newtheorem"),
+    _T ("newcounter"),
+    _T ("setcounter"),
+    _T ("addtocounter"),
+    _T ("value"),
+    _T ("stepcounter"),
+
+    _T ("newlength"),
+    _T ("setlength"),
+    _T ("addtolength"),
+    _T ("settowidth"),
+    _T ("textheight"),
+    _T ("textwidth"),
+    _T ("topmargin"),
+    _T ("hoffset"),
+    _T ("voffset"),
+    _T ("oddsidemargin"),
+    _T ("evensidemargin"),
+    _T ("mbox"),
+    _T ("makebox"),
+    _T ("fbos"),
+    _T ("framebox"),
+    _T ("newsavebox"),
+    _T ("sbox"),
+    _T ("savebox"),
+    _T ("usebox"),
+    _T ("raisebox"),
+    _T ("put"),
+    _T ("framebox"),
+    _T ("dashbox"),
+    _T ("line"),
+    _T ("vector"),
+    _T ("circle"),
+    _T ("oval"),
+    _T ("frame"),
+    _T ("shortstack"),
+    _T ("multiput"),
+    _T ("thinlines"),
+    _T ("thicklines"),
+    _T ("linethickness"),
+    _T ("font"),
+    _T ("magnification"),
+    _T ("magstephalf"),
+    _T ("magstep"),
+    _T ("hsize"),
+    _T ("vsize"),
+    _T ("voffset"),
+    _T ("hoffset"),
+    _T ("topskip"),
+    _T ("leftskip"),
+    _T ("rightskip"),
+    _T ("eject"),
+    _T ("vfill"),
+    _T ("eject"),
+    _T ("goodbreak"),
+    _T ("nobreak"),
+    _T ("nopagenumbers"),
+    _T ("headline"),
+    _T ("headheight"),
+    _T ("headsep"),
+    _T ("footnote"),
+    _T ("pageno"),
+    _T ("folio"),
+    _T ("par"),
+    _T ("parindent"),
+    _T ("noindent"),
+    _T ("break"),
+    _T ("hfill"),
+    _T ("break"),
+    _T ("line"),
+    _T ("rightline"),
+    _T ("centerline"),
+
+    _T ("includegraphics"),
+
+    _T ("enskip"),
+    _T ("hskip"),
+    _T ("hfil"),
+    _T ("hfill"),
+    _T ("hss"),
+    _T ("smallskip"),
+    _T ("vskip"),
+    _T ("vglue"),
+    _T ("vfil"),
+    _T ("vfill"),
+    _T ("vss"),
+    _T ("baselineskip"),
+    _T ("parskip"),
+    _T ("topinsert"),
+    _T ("midinsert"),
+    _T ("handindent"),
+    _T ("footnote"),
+    _T ("hrule"),
+    _T ("vrule"),
+    _T ("leaders"),
+    _T ("hrulefill"),
+    _T ("settabs"),
+    _T ("haling"),
+    _T ("hbox"),
+    _T ("vbox"),
+    _T ("newbox"),
+    _T ("setbox"),
+
+    _T ("arccos"),
+    _T ("cos"),
+    _T ("csc"),
+    _T ("exp"),
+    _T ("ker"),
+    _T ("limsup"),
+    _T ("min"),
+    _T ("sinh"),
+    _T ("arcsin"),
+    _T ("cosh"),
+    _T ("deg"),
+    _T ("gcd"),
+    _T ("lg"),
+    _T ("ln"),
+    _T ("Pr"),
+    _T ("sup"),
+    _T ("arctan"),
+    _T ("cot"),
+    _T ("det"),
+    _T ("hom"),
+    _T ("lim"),
+    _T ("log"),
+    _T ("sec"),
+    _T ("tan"),
+    _T ("arg"),
+    _T ("coth"),
+    _T ("dim"),
+    _T ("inf"),
+    _T ("liminfo"),
+    _T ("max"),
+    _T ("sin"),
+    _T ("tanh"),
+
+    _T ("displaystyle"),
+    _T ("textstyle"),
+    _T ("alpha"),
+    _T ("beta"),
+    _T ("gamma"),
+    _T ("delta"),
+    _T ("epsilon"),
+    _T ("varepsilon"),
+    _T ("zeta"),
+    _T ("eta"),
+    _T ("theta"),
+    _T ("vartheta"),
+    _T ("iota"),
+    _T ("kappa"),
+    _T ("lambda"),
+    _T ("mu"),
+    _T ("nu"),
+    _T ("xi"),
+    _T ("o"),
+    _T ("pi"),
+    _T ("varpi"),
+    _T ("rho"),
+    _T ("varrho"),
+    _T ("sigma"),
+    _T ("varsigma"),
+    _T ("tau"),
+    _T ("upsilon"),
+    _T ("phi"),
+    _T ("varphi"),
+    _T ("chi"),
+    _T ("psi"),
+    _T ("omega"),
+    _T ("Gamma"),
+    _T ("Delta"),
+    _T ("Theta"),
+    _T ("Lambda"),
+    _T ("Xi"),
+    _T ("Pi"),
+    _T ("Sigma"),
+    _T ("Upsilon"),
+    _T ("Phi"),
+    _T ("Psi"),
+    _T ("Omega"),
+
+    _T ("aleph"),
+    _T ("hbar"),
+    _T ("imath"),
+    _T ("jmath"),
+    _T ("ell"),
+    _T ("wp"),
+    _T ("Re"),
+    _T ("Im"),
+    _T ("partial"),
+    _T ("infty"),
+    _T ("backslash"),
+    _T ("prime"),
+    _T ("emptyset"),
+    _T ("nabla"),
+    _T ("surd"),
+    _T ("triangle"),
+    _T ("angle"),
+    _T ("bot"),
+    _T ("top"),
+    _T ("forall"),
+    _T ("exists"),
+    _T ("neg"),
+    _T ("lnot"),
+    _T ("flat"),
+    _T ("natural"),
+    _T ("sharp"),
+    _T ("clubsuit"),
+    _T ("diamondsuit"),
+    _T ("heartsuit"),
+    _T ("spadesuit"),
+
+    _T ("pm"),
+    _T ("mp"),
+    _T ("setminus"),
+    _T ("cdot"),
+    _T ("times"),
+    _T ("ast"),
+    _T ("star"),
+    _T ("diamond"),
+    _T ("circ"),
+    _T ("bullet"),
+    _T ("triangleleft"),
+    _T ("cap"),
+    _T ("cup"),
+    _T ("uplus"),
+    _T ("sqcap"),
+    _T ("sqcup"),
+    _T ("amalg"),
+    _T ("div"),
+    _T ("wr"),
+    _T ("bigcirc"),
+    _T ("vee"),
+    _T ("lor"),
+    _T ("wedge"),
+    _T ("land"),
+    _T ("oplus"),
+    _T ("ominus"),
+    _T ("otimes"),
+    _T ("oslash"),
+    _T ("odot"),
+    _T ("dagger"),
+    _T ("ddagger"),
+    _T ("bigtriangleleft"),
+    _T ("bigtriangledown"),
+    _T ("sum"),
+    _T ("prod"),
+    _T ("coprod"),
+    _T ("int"),
+    _T ("oint"),
+    _T ("bigcap"),
+    _T ("bigcup"),
+    _T ("bigsqcup"),
+    _T ("bigvee"),
+    _T ("bigwedge"),
+    _T ("bigodot"),
+    _T ("bigotimes"),
+    _T ("bigoplus"),
+    _T ("biguplus"),
+    _T ("hat"),
+    _T ("acute"),
+    _T ("ddot"),
+    _T ("vec"),
+    _T ("check"),
+    _T ("grave"),
+    _T ("breve"),
+    _T ("tilde"),
+    _T ("dot"),
+    _T ("bar"),
+    _T ("widehat"),
+    _T ("widetilde"),
+
+    _T ("ldots"),
+    _T ("vdots"),
+    _T ("cdots"),
+    _T ("ddots"),
+    _T ("leq"),
+    _T ("le"),
+    _T ("prec"),
+    _T ("preceq"),
+    _T ("ll"),
+    _T ("subset"),
+    _T ("subsetqe"),
+    _T ("supsetqe"),
+    _T ("in"),
+    _T ("vdash"),
+    _T ("smile"),
+    _T ("frown"),
+    _T ("geq"),
+    _T ("ge"),
+    _T ("succ"),
+    _T ("succeq"),
+    _T ("gg"),
+    _T ("supset"),
+    _T ("sqsubseteq"),
+    _T ("sqsupsetqe"),
+    _T ("ni"),
+    _T ("owns"),
+    _T ("dashv"),
+    _T ("mid"),
+    _T ("parallel"),
+    _T ("equiv"),
+    _T ("sim"),
+    _T ("simeq"),
+    _T ("asymp"),
+    _T ("approx"),
+    _T ("cong"),
+    _T ("bowtie"),
+    _T ("propto"),
+    _T ("models"),
+    _T ("doteq"),
+    _T ("perp"),
+    _T ("not"),
+
+    _T ("leftarrow"),
+    _T ("Leftarrow"),
+    _T ("gets"),
+    _T ("longleftarrow"),
+    _T ("Longleftarrow"),
+    _T ("rightarrow"),
+    _T ("Rightarrow"),
+    _T ("to"),
+    _T ("longrightarrow"),
+    _T ("Longrightarrow"),
+    _T ("leftrightarrow"),
+    _T ("Leftrightarrow"),
+    _T ("longleftrightarrow"),
+    _T ("Longleftrightarrow"),
+    _T ("mapsto"),
+    _T ("longmapsto"),
+    _T ("hookleftarrow"),
+    _T ("hookrightarrow"),
+    _T ("leftharpoonup"),
+    _T ("rightharpoonup"),
+    _T ("leftharpoondown"),
+    _T ("rightharpoondown"),
+    _T ("uparrow"),
+    _T ("Uparrow"),
+    _T ("downarrow"),
+    _T ("Downarrow"),
+    _T ("updownarrow"),
+    _T ("Updownarrow"),
+    _T ("nearrow"),
+    _T ("searrow"),
+    _T ("swarrow"),
+    _T ("nwarrow"),
+    _T ("lbrack"),
+    _T ("lfloor"),
+    _T ("rbrack"),
+    _T ("rfloor"),
+    _T ("lceil"),
+    _T ("lbrace"),
+    _T ("langle"),
+    _T ("rceil"),
+    _T ("rbrace"),
+    _T ("rangle"),
+    _T ("quad"),
+    _T ("qquad"),
+
+    _T ("Biggl"),
+    _T ("biggl"),
+    _T ("Bigl"),
+    _T ("bigl"),
+    _T ("bigr"),
+    _T ("Bigr"),
+    _T ("biggr"),
+    _T ("Biggr"),
+    _T ("lgroup"),
+    _T ("rgroup"),
+    _T ("langle"),
+    _T ("rangle"),
+    _T ("vert"),
+    _T ("Vert"),
+    _T ("uparrow"),
+    _T ("left"),
+    _T ("right"),
+    _T ("overline"),
+    _T ("overrightarrow"),
+    _T ("overleftarrow"),
+    _T ("overbrace"),
+    _T ("underbrace"),
+    _T ("atop"),
+    _T ("choose"),
+    _T ("brack"),
+    _T ("above"),
+    _T ("brace"),
+    _T ("pmatrix"),
+    _T ("matrix"),
+    _T ("bordermatrix"),
+    _T ("eqalign"),
+    _T ("eqno"),
+    _T ("eqalignno"),
+    _T ("quad"),
+
+    _T ("def"),
+    _T ("gdef"),
+    _T ("edef"),
+    _T ("newcount"),
+    _T ("advance"),
+    _T ("multiply"),
+    _T ("divide"),
+    _T ("number"),
+    _T ("romannumeral"),
+    _T ("newdimen"),
+    _T ("newread"),
+    _T ("openin"),
+    _T ("closein"),
+    _T ("input"),
+    _T ("endinput"),
+    _T ("newwrite"),
+    _T ("openouput"),
+    _T ("closeout"),
+    _T ("write"),
+    _T ("jobname"),
+    _T ("if"),
+    _T ("else"),
+    _T ("fi"),
+    _T ("ifx"),
+    _T ("ifeof"),
+    _T ("ifhmode"),
+    _T ("ifvmode"),
+    _T ("ifmmode"),
+    _T ("ifcat"),
+    _T ("ifnum"),
+    _T ("ifdim"),
+    _T ("ifodd"),
+    _T ("ifcase"),
+    _T ("or"),
+    _T ("loop"),
+    _T ("repeat"),
+
+    _T ("beginpicture"),
+    _T ("setcoordinatesystem"),
+    _T ("endpicture"),
+    _T ("plotheading"),
+    _T ("lines"),
+    _T ("putrule"),
+    _T ("linethickness"),
+    _T ("setlinear"),
+    _T ("setquadratic"),
+    _T ("sethistograms"),
+    _T ("setsolid"),
+    _T ("setdashes"),
+    _T ("setdots"),
+    _T ("setdashpattern"),
+    _T ("setplotsymbol"),
+    _T ("plot"),
+    _T ("arrow"),
+    _T ("put"),
+    _T ("multiput"),
+    _T ("circulararc"),
+    _T ("ellipticarc"),
+    _T ("startrotation"),
+    _T ("stoprotation"),
+    _T ("setshadegrid"),
+    _T ("setshadesymbol"),
+    _T ("shaderectangleson"),
+    _T ("sharerectanglesoff"),
+    _T ("vshade"),
+    _T ("setquadratic"),
+    _T ("hshade"),
+    _T ("setplotarea"),
+    _T ("inboundscheckon"),
+    _T ("inboundscheckoff"),
+    _T ("axis"),
+    _T ("setbox"),
+    _T ("endpicturesave"),
+    _T ("newdimen"),
+    NULL
+  };
+
+static LPTSTR s_apszUser1KeywordList[] =
+  {
+    _T ("Alph"),
+    _T ("AtBeginDocument"),
+    _T ("AtBeginDvi"),
+    _T ("AtEndDocument"),
+    _T ("AtEndOfPackage"),
+    _T ("Big"),
+    _T ("Bigg"),
+    _T ("Box"),
+    _T ("CheckCommand"),
+    _T ("ClassError"),
+    _T ("ClassInfo"),
+    _T ("ClassWarning"),
+    _T ("ClassWarningNoLine"),
+    _T ("DeclareErrorFont"),
+    _T ("DeclareFixedFont"),
+    _T ("DeclareFontEncoding"),
+    _T ("DeclareFontEncodingDefaults"),
+    _T ("DeclareFontFamily"),
+    _T ("DeclareFontShape"),
+    _T ("DeclareFontSubstitution"),
+    _T ("DeclareMathAccent"),
+    _T ("DeclareMathAlphabet"),
+    _T ("DeclareMathDelimiter"),
+    _T ("DeclareMathRadical"),
+    _T ("DeclareMathSizes"),
+    _T ("DeclareMathSymbol"),
+    _T ("DeclareMathVersion"),
+    _T ("DeclareOldFontCommand"),
+    _T ("DeclareOption"),
+    _T ("DeclarePreloadSizes"),
+    _T ("DeclareRobustCommand"),
+    _T ("DeclareSizeFunction"),
+    _T ("DeclareSymbolFont"),
+    _T ("DeclareSymbolFontAlphabet"),
+    _T ("DeclareTextAccent"),
+    _T ("DeclareTextAccentDefault"),
+    _T ("DeclareTextCommand"),
+    _T ("DeclareTextCommandDefault"),
+    _T ("DeclareTextComposite"),
+    _T ("DeclareTextCompositeCommand"),
+    _T ("DeclareTextFontCommand"),
+    _T ("DeclareTextSymbol"),
+    _T ("DeclareTextSymbolDefault"),
+    _T ("ExecuteOptions"),
+    _T ("IfFileExists"),
+    _T ("InputIfFileExists"),
+    _T ("Join"),
+    _T ("LoadClass"),
+    _T ("LoadClassWithOptions"),
+    _T ("MessageBreak"),
+    _T ("NeedsTeXFormat"),
+    _T ("OptionNotUsed"),
+    _T ("PackageError"),
+    _T ("PackageInfo"),
+    _T ("PackageWarning"),
+    _T ("PackageWarningNoLine"),
+    _T ("PassOptionsToClass"),
+    _T ("PassOptionsToPackage"),
+    _T ("ProcessOptions"),
+    _T ("ProvideTextCommand"),
+    _T ("ProvideTextCommandDefault"),
+    _T ("ProvidesFile"),
+    _T ("ProvidesPackage"),
+    _T ("RequirePackage"),
+    _T ("RequirePackageWithOptions"),
+    _T ("Roman"),
+    _T ("SetMathAlphabet"),
+    _T ("SetSymbolFont"),
+    _T ("TeX"),
+    _T ("TextSymbolUnavailable"),
+    _T ("UseTextAccent"),
+    _T ("UseTextSymbol"),
+    _T ("addcontentsline"),
+    _T ("addpenalty"),
+    _T ("addtocontents"),
+    _T ("addtoversion"),
+    _T ("addvspace"),
+    _T ("afterassignment"),
+    _T ("allocationnumber"),
+    _T ("allowbreak"),
+    _T ("alph"),
+    _T ("arrayrulewidth"),
+    _T ("arraystretch"),
+    _T ("baselinestretch"),
+    _T ("bezier"),
+    _T ("bfdefault"),
+    _T ("bfseries"),
+    _T ("bibcite"),
+    _T ("bibliography"),
+    _T ("bibliographystyle"),
+    _T ("big"),
+    _T ("bigbreak"),
+    _T ("bigg"),
+    _T ("bigskip"),
+    _T ("bigskipamount"),
+    _T ("bigskipamount"),
+    _T ("bmod"),
+    _T ("boldmath"),
+    _T ("buildrel"),
+    _T ("cases"),
+    _T ("catcode"),
+    _T ("center"),
+    _T ("centering"),
+    _T ("chardef"),
+    _T ("cleardoublepage"),
+    _T ("contentsline"),
+    _T ("countdef"),
+    _T ("cr"),
+    _T ("csname"),
+    _T ("depth"),
+    _T ("discretionary"),
+    _T ("displaymath"),
+    _T ("dospecials"),
+    _T ("dotfill"),
+    _T ("encodingdefault"),
+    _T ("endcsname"),
+    _T ("everycr"),
+    _T ("expandafter"),
+    _T ("expandafter"),
+    _T ("extracolsep"),
+    _T ("familydefault"),
+    _T ("familydefault"),
+    _T ("fbox"),
+    _T ("filbreak"),
+    _T ("flushleft"),
+    _T ("flushright"),
+    _T ("fmtname"),
+    _T ("fmtversion"),
+    _T ("fontencoding"),
+    _T ("fontfamily"),
+    _T ("fontseries"),
+    _T ("fontshape"),
+    _T ("footnotemark"),
+    _T ("footnoterule"),
+    _T ("footnotetext"),
+    _T ("frac"),
+    _T ("frenchspacing"),
+    _T ("fussy"),
+    _T ("futurelet"),
+    _T ("global"),
+    _T ("glossary"),
+    _T ("halign"),
+    _T ("height"),
+    _T ("hphantom"),
+    _T ("ifinner"),
+    _T ("immediate"),
+    _T ("include"),
+    _T ("includeonly"),
+    _T ("itdefault"),
+    _T ("iterate"),
+    _T ("kern"),
+    _T ("lastskip"),
+    _T ("leadsto"),
+    _T ("leavevmode"),
+    _T ("lefteqn"),
+    _T ("leftline"),
+    _T ("leftmark"),
+    _T ("let"),
+    _T ("lhd"),
+    _T ("liminf"),
+    _T ("lineskip"),
+    _T ("lower"),
+    _T ("lowercase"),
+    _T ("makeatletter"),
+    _T ("makeatother"),
+    _T ("makeglossary"),
+    _T ("makeindex"),
+    _T ("marginpar"),
+    _T ("markboth"),
+    _T ("markright"),
+    _T ("mathclose"),
+    _T ("mathop"),
+    _T ("mathopen"),
+    _T ("mathrel"),
+    _T ("mathstrut"),
+    _T ("mddefault"),
+    _T ("medbreak"),
+    _T ("medmuskip"),
+    _T ("medskip"),
+    _T ("mho"),
+    _T ("minipage"),
+    _T ("mskip"),
+    _T ("multispan"),
+    _T ("narrower"),
+    _T ("negthinspace"),
+    _T ("newfont"),
+    _T ("newhelp"),
+    _T ("newif"),
+    _T ("newinsert"),
+    _T ("newlabel"),
+    _T ("newlanguage"),
+    _T ("newline"),
+    _T ("newmathalphabet"),
+    _T ("newmuskip"),
+    _T ("newskip"),
+    _T ("newtoks"),
+    _T ("nocite"),
+    _T ("nocorrlist"),
+    _T ("noexpand"),
+    _T ("nointerlineskip"),
+    _T ("nolimits"),
+    _T ("nonfrenchspacing"),
+    _T ("nonumber"),
+    _T ("normalbaselines"),
+    _T ("normallineskip"),
+    _T ("normalmarginpar"),
+    _T ("null"),
+    _T ("numberline"),
+    _T ("obeylines"),
+    _T ("obeyspaces"),
+    _T ("offinterlineskip"),
+    _T ("onecolumn"),
+    _T ("openup"),
+    _T ("pagenumberin"),
+    _T ("parbox"),
+    _T ("penalty"),
+    _T ("phantom"),
+    _T ("pmod"),
+    _T ("protect"),
+    _T ("providecommand"),
+    _T ("raggedbottom"),
+    _T ("raggedleft"),
+    _T ("raggedright"),
+    _T ("refstepcounter"),
+    _T ("relax"),
+    _T ("removelastskip"),
+    _T ("renewenvironment"),
+    _T ("reversemarginpar"),
+    _T ("rhd"),
+    _T ("rightmark"),
+    _T ("rlap"),
+    _T ("rmdefault"),
+    _T ("roman"),
+    _T ("root"),
+    _T ("rq"),
+    _T ("rule"),
+    _T ("scdefault"),
+    _T ("secdef"),
+    _T ("selectfont"),
+    _T ("seriesdefault"),
+    _T ("settodepth"),
+    _T ("settoheight"),
+    _T ("sfdefault"),
+    _T ("shapedefault"),
+    _T ("showhyphens"),
+    _T ("showoutput"),
+    _T ("showoverfull"),
+    _T ("sldefault"),
+    _T ("sloppy"),
+    _T ("sloppypar"),
+    _T ("smallbreak"),
+    _T ("space"),
+    _T ("spacefactor"),
+    _T ("sqsubset"),
+    _T ("stackrel"),
+    _T ("stretch"),
+    _T ("strut"),
+    _T ("suppressfloats"),
+    _T ("symbol"),
+    _T ("tabskip"),
+    _T ("thanks"),
+    _T ("thefootnote"),
+    _T ("thickmuskip"),
+    _T ("thinmuskip"),
+    _T ("thinspace"),
+    _T ("today"),
+    _T ("tracingfonts"),
+    _T ("tracingoutput"),
+    _T ("trivlist"),
+    _T ("ttdefault"),
+    _T ("twocolumn"),
+    _T ("typein"),
+    _T ("typeout"),
+    _T ("unboldmath"),
+    _T ("undefinedpagestyle"),
+    _T ("underbar"),
+    _T ("underline"),
+    _T ("unlhd"),
+    _T ("unrhd"),
+    _T ("updefault"),
+    _T ("usecounter"),
+    _T ("usefont"),
+    _T ("usepackage"),
+    _T ("vcenter"),
+    _T ("verb"),
+    _T ("verbatim"),
+    _T ("vline"),
+    _T ("vphantom"),
+    _T ("width"),
+    _T ("wlog"),
+    _T ("xdef"),
+    NULL
+  };
+
+static BOOL
+IsXKeyword (LPTSTR apszKeywords[], LPCTSTR pszChars, int nLength)
+{
+  for (int L = 0; apszKeywords[L] != NULL; L++)
+    {
+      if (_tcsnicmp (apszKeywords[L], pszChars, nLength) == 0
+            && apszKeywords[L][nLength] == 0)
+        return TRUE;
+    }
+  return FALSE;
+}
+
+static BOOL
+IsTexKeyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszTexKeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsUser1Keyword (LPCTSTR pszChars, int nLength)
+{
+  return IsXKeyword (s_apszUser1KeywordList, pszChars, nLength);
+}
+
+static BOOL
+IsTexNumber (LPCTSTR pszChars, int nLength)
+{
+  if (nLength > 2 && pszChars[0] == '0' && pszChars[1] == 'x')
+    {
+      for (int I = 2; I < nLength; I++)
+        {
+          if (_istdigit (pszChars[I]) || (pszChars[I] >= 'A' && pszChars[I] <= 'F') ||
+                (pszChars[I] >= 'a' && pszChars[I] <= 'f'))
+            continue;
+          return FALSE;
+        }
+      return TRUE;
+    }
+  if (!_istdigit (pszChars[0]))
+    return FALSE;
+  for (int I = 1; I < nLength; I++)
+    {
+      if (!_istdigit (pszChars[I]) && pszChars[I] != '+' &&
+            pszChars[I] != '-' && pszChars[I] != '.' && pszChars[I] != 'e' &&
+            pszChars[I] != 'E')
+        return FALSE;
+    }
+  return TRUE;
+}
+
+#define DEFINE_BLOCK(pos, colorindex)   \
+ASSERT((pos) >= 0 && (pos) <= nLength);\
+if (pBuf != NULL)\
+  {\
+    if (nActualItems == 0 || pBuf[nActualItems - 1].m_nCharPos <= (pos)){\
+        pBuf[nActualItems].m_nCharPos = (pos);\
+        pBuf[nActualItems].m_nColorIndex = (colorindex);\
+        nActualItems ++;}\
+  }
+
+#define COOKIE_COMMENT          0x0001
+#define COOKIE_PREPROCESSOR     0x0002
+#define COOKIE_EXT_COMMENT      0x0004
+#define COOKIE_STRING           0x0008
+#define COOKIE_CHAR             0x0010
+
+DWORD CCrystalTextView::
+ParseLineTex (DWORD dwCookie, int nLineIndex, TEXTBLOCK * pBuf, int &nActualItems)
+{
+  int nLength = GetLineLength (nLineIndex);
+  if (nLength <= 1)
+    return dwCookie & COOKIE_EXT_COMMENT;
+
+  LPCTSTR pszChars = GetLineChars (nLineIndex);
+  BOOL bFirstChar = (dwCookie & ~COOKIE_EXT_COMMENT) == 0;
+  BOOL bRedefineBlock = TRUE;
+  BOOL bDecIndex = FALSE;
+  int nIdentBegin = -1;
+
+  for (int I = 0;; I++)
+    {
+      if (bRedefineBlock)
+        {
+          int nPos = I;
+          if (bDecIndex)
+            nPos--;
+          if (dwCookie & (COOKIE_COMMENT | COOKIE_EXT_COMMENT))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_COMMENT);
+            }
+          else if (dwCookie & (COOKIE_CHAR | COOKIE_STRING))
+            {
+              DEFINE_BLOCK (nPos, COLORINDEX_STRING);
+            }
+          else
+            {
+              if (xisalnum (pszChars[nPos]) || pszChars[nPos] == '.')
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_NORMALTEXT);
+                }
+              else
+                {
+                  DEFINE_BLOCK (nPos, COLORINDEX_OPERATOR);
+                  bRedefineBlock = TRUE;
+                  bDecIndex = TRUE;
+                  goto out;
+                }
+            }
+          bRedefineBlock = FALSE;
+          bDecIndex = FALSE;
+        }
+out:
+
+      if (I == nLength)
+        break;
+
+      if (dwCookie & COOKIE_COMMENT)
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  String constant "...."
+      if (dwCookie & COOKIE_STRING)
+        {
+          if (pszChars[I] == '"' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_STRING;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      //  Char constant '..'
+      if (dwCookie & COOKIE_CHAR)
+        {
+          if (pszChars[I] == '\'' && (I == 0 || I == 1 && pszChars[I - 1] != '\\' || I >= 2 && (pszChars[I - 1] != '\\' || pszChars[I - 1] == '\\' && pszChars[I - 2] == '\\')))
+            {
+              dwCookie &= ~COOKIE_CHAR;
+              bRedefineBlock = TRUE;
+            }
+          continue;
+        }
+
+      if (pszChars[I] == '%')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_COMMENT);
+          dwCookie |= COOKIE_COMMENT;
+          break;
+        }
+
+      //  Normal text
+      if (pszChars[I] == '"')
+        {
+          DEFINE_BLOCK (I, COLORINDEX_STRING);
+          dwCookie |= COOKIE_STRING;
+          continue;
+        }
+      if (pszChars[I] == '\'')
+        {
+          // if (I + 1 < nLength && pszChars[I + 1] == '\'' || I + 2 < nLength && pszChars[I + 1] != '\\' && pszChars[I + 2] == '\'' || I + 3 < nLength && pszChars[I + 1] == '\\' && pszChars[I + 3] == '\'')
+          if (!I || !xisalnum (pszChars[I - 1]))
+            {
+              DEFINE_BLOCK (I, COLORINDEX_STRING);
+              dwCookie |= COOKIE_CHAR;
+              continue;
+            }
+        }
+
+      if (bFirstChar)
+        {
+          if (!isspace (pszChars[I]))
+            bFirstChar = FALSE;
+        }
+
+      if (pBuf == NULL)
+        continue;               //  We don't need to extract keywords,
+      //  for faster parsing skip the rest of loop
+
+      if (xisalnum (pszChars[I]) || pszChars[I] == '.')
+        {
+          if (nIdentBegin == -1)
+            nIdentBegin = I;
+        }
+      else
+        {
+          if (nIdentBegin >= 0)
+            {
+              if (IsTexKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+                }
+              else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+                }
+              else if (IsTexNumber (pszChars + nIdentBegin, I - nIdentBegin))
+                {
+                  DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+                }
+              else
+                {
+                  bool bFunction = FALSE;
+
+                  if (!bFunction)
+                    {
+                      for (int j = I; j >= 0; j--)
+                        {
+                          if (!isspace (pszChars[j]))
+                            {
+                              if (pszChars[j] == '$')
+                                {
+                                  bFunction = TRUE;
+                                }
+                              break;
+                            }
+                        }
+                    }
+                  if (bFunction)
+                    {
+                      DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+                    }
+                }
+              bRedefineBlock = TRUE;
+              bDecIndex = TRUE;
+              nIdentBegin = -1;
+            }
+        }
+    }
+
+  if (nIdentBegin >= 0)
+    {
+      if (IsTexKeyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_KEYWORD);
+        }
+      else if (IsUser1Keyword (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_USER1);
+        }
+      else if (IsTexNumber (pszChars + nIdentBegin, I - nIdentBegin))
+        {
+          DEFINE_BLOCK (nIdentBegin, COLORINDEX_NUMBER);
+        }
+      else
+        {
+          bool bFunction = FALSE;
+
+          if (!bFunction)
+            {
+              for (int j = I; j >= 0; j--)
+                {
+                  if (!isspace (pszChars[j]))
+                    {
+                      if (pszChars[j] == '$')
+                        {
+                          bFunction = TRUE;
+                        }
+                      break;
+                    }
+                }
+            }
+          if (bFunction)
+            {
+              DEFINE_BLOCK (nIdentBegin, COLORINDEX_FUNCNAME);
+            }
+        }
+    }
+
+  dwCookie &= COOKIE_EXT_COMMENT;
+  return dwCookie;
+}
diff --git a/Src/editlib/wispelld.h b/Src/editlib/wispelld.h
new file mode 100644 (file)
index 0000000..968e362
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  The following ifdef block is the standard way of creating macros which make exporting 
+ *  from a DLL simpler. All files within this DLL are compiled with the WISPELL_EXPORTS
+ *  symbol defined on the command line. this symbol should not be defined on any project
+ *  that uses this DLL. This way any other project whose source files include this file see 
+ *  WISPELL_API functions as being imported from a DLL, wheras this DLL sees symbols
+ *  defined with this macro as being exported.
+ */
+
+#ifndef __WISPELLD_H__
+#define __WISPELLD_H__
+
+/*#ifdef WISPELL_EXPORTS
+#define WISPELL_API __declspec (dllexport)
+#else
+#define WISPELL_API __declspec (dllimport)
+#endif*/
+
+#define SN_FOUND       1 /* possibly incorrect word was found */
+#define SN_REPLACED    2 /* possibly incorrect word was commanded to be replaced */
+#define SN_FINISHED    3 /* spell checking finished */
+#define SN_HELP_SPELL  4 /* help button of the checking dialog was pressed */
+#define SN_HELP_CONFIG 5 /* help button of the configuration dialog was pressed */
+
+#define SF_TEX         0x00001 /* -t/-n */  /* TeX mode on */
+#define SF_HTML        0x00002 /* -h    */  /* HTML mode on */
+#define SF_RUNTOGETHER 0x00004 /* -C/-B */  /* run-together words to be legal compounds */
+#define SF_EXTRAAFFIX  0x00008 /* -m/-P */  /* generate extra root/affix combinations */
+#define SF_SORTPROBLY  0x00010 /* -S    */  /* sort the list of suggested words by probable correctness */
+#define SF_HELP        0x10000              /* to enable the Help button in checking and configuration dialogs */
+#define SF_ISPELLPATH  0x20000              /* to enable setting of the directory where ispell resides */
+
+#define SF_TOSET (SF_TEX|SF_HTML|SF_RUNTOGETHER|SF_EXTRAAFFIX|SF_SORTPROBLY)
+
+#define BUFSIZE 4096
+#define INPUTWORDLEN 100
+#define WAITTIME 50
+
+typedef struct SpellData_t
+  {
+    DWORD dwFlags;                            /* combination of SF_ flags */
+    TCHAR szIspell[MAX_PATH],                 /* the directory where ispell resides */
+          szUserDict[MAX_PATH],               /* path to the user dictionary */
+          szMainDict[INPUTWORDLEN],           /* name of the file with the main dictionary */
+          szWordChars[INPUTWORDLEN],          /* extra characters to be allowed to build the word */
+          szFormatter[INPUTWORDLEN];          /* alternate form for the character set */
+    HWND hParent;                             /* parent window for the calling of the current routine */
+    LPCTSTR pszWord;                          /* currently processed word - found or to be replaced */
+    LPTSTR pszBuffer,                         /* buffer from which the engine reads the input line */
+           pszCurrent;                        /* current position in the buffer - for internal use only */
+    int nColumn,                              /* character position in currently processed line */
+        nRow,                                 /* currently processed line */
+        nDelta,                               /* gap between original column and another one modified by replacing - for internal use only */
+        nLegalLen;                            /* maximal length of the word considered to be always correct */
+    LPVOID pUserData;                         /* for external use only */
+    int (*GetLine) (struct SpellData_t*);     /* pointer to routine which has to fill in the input buffer */
+    int (*Notify) (int, struct SpellData_t*); /* pointer to routine which receives SN_ notifications */
+  } SpellData;
+
+/* WISPELL_API int SpellInit (SpellData*); */   /* initializes the control structure */
+/* WISPELL_API int SpellCheck (SpellData*); */  /* performs spell checking (the dialog may appear) */
+/* WISPELL_API int SpellConfig (SpellData*); */ /* performs spell checking configuration (the dialog appears) */
+
+#endif /* __WISPELLD_H__ */