home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2006 April / DPPRO0406DVD.ISO / Essentials / Programming / Notepad2 / Source / NP2SRC.ZIP / Edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-06-25  |  70.2 KB  |  2,376 lines

  1. /******************************************************************************
  2. *
  3. *
  4. * Notepad2
  5. *
  6. * Edit.c
  7. *   Text File Editing Helper Stuff
  8. *
  9. * See Readme.txt for more information about this source code.
  10. * Please send me your comments to this work.
  11. *
  12. * Distributed under the terms of the GNU General Public License,
  13. * see License.txt for details.
  14. *
  15. *                                              (c) Florian Balmer 1996-2004
  16. *                                                       textview@bluewin.ch
  17. *                                               http://www.flos-freeware.ch
  18. *
  19. *
  20. ******************************************************************************/
  21. #include <windows.h>
  22. #include <commctrl.h>
  23. #include <commdlg.h>
  24. #include <string.h>
  25. #include "notepad2.h"
  26. #include "helpers.h"
  27. #include "dialogs.h"
  28. #include "appreg.h"
  29. #include "scintilla.h"
  30. #include "scilexer.h"
  31. #include "styles.h"
  32. #include "edit.h"
  33. #include "resource.h"
  34.  
  35.  
  36. extern HWND  hwndMain;
  37. extern HWND  hwndEdit;
  38. extern HINSTANCE g_hInstance;
  39. extern LPMALLOC  g_lpMalloc;
  40.  
  41.  
  42. // Default Codepage and Character Set
  43. extern int iDefaultCodePage;
  44. extern int iDefaultCharSet;
  45.  
  46.  
  47. //=============================================================================
  48. //
  49. //  EditCreate()
  50. //
  51. HWND EditCreate(HWND hwndParent)
  52. {
  53.  
  54.   HWND hwnd;
  55.  
  56.   hwnd = CreateWindowEx(
  57.            WS_EX_CLIENTEDGE,
  58.            "Scintilla",
  59.            NULL,
  60.            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
  61.            0,0,0,0,
  62.            hwndParent,
  63.            (HMENU)IDC_EDIT,
  64.            g_hInstance,
  65.            NULL);
  66.  
  67.   SendMessage(hwnd,SCI_SETCODEPAGE,iDefaultCodePage,0);
  68.   SendMessage(hwnd,SCI_SETEOLMODE,SC_EOL_CRLF,0);
  69.  
  70.   SendMessage(hwnd,SCI_SETMODEVENTMASK,/*SC_MODEVENTMASKALL*/SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT,0);
  71.  
  72.   SendMessage(hwnd,SCI_USEPOPUP,FALSE,0);
  73.  
  74.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_NEXT + (SCMOD_CTRL << 16)),SCI_PARADOWN);
  75.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_PRIOR + (SCMOD_CTRL << 16)),SCI_PARAUP);
  76.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_NEXT + ((SCMOD_CTRL | SCMOD_SHIFT) << 16)),SCI_PARADOWNEXTEND);
  77.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_PRIOR + ((SCMOD_CTRL | SCMOD_SHIFT) << 16)),SCI_PARAUPEXTEND);
  78.  
  79.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_HOME + (0 << 16)),SCI_VCHOMEWRAP);
  80.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_END + (0 << 16)),SCI_LINEENDWRAP);
  81.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_HOME + (SCMOD_SHIFT << 16)),SCI_VCHOMEWRAPEXTEND);
  82.   SendMessage(hwnd,SCI_ASSIGNCMDKEY,(SCK_END + (SCMOD_SHIFT << 16)),SCI_LINEENDWRAPEXTEND);
  83.  
  84.   // Init default values for printing
  85.   EditPrintInit();
  86.  
  87.   return(hwnd);
  88.  
  89. }
  90.  
  91.  
  92. //=============================================================================
  93. //
  94. //  EditSetNewText()
  95. //
  96. void EditSetNewText(HWND hwnd,LPCSTR lpstrText,DWORD cbText)
  97. {
  98.  
  99.   if (SendMessage(hwnd,SCI_GETREADONLY,0,0))
  100.     SendMessage(hwnd,SCI_SETREADONLY,FALSE,0);
  101.  
  102.   SendMessage(hwnd,SCI_CANCEL,0,0);
  103.   SendMessage(hwnd,SCI_SETUNDOCOLLECTION,0,0);
  104.   SendMessage(hwnd,SCI_CLEARALL,0,0);
  105.   SendMessage(hwnd,SCI_MARKERDELETEALL,(WPARAM)-1,0);
  106.  
  107.   if (cbText > 0)
  108.     SendMessage(hwnd,SCI_ADDTEXT,cbText,(LPARAM)lpstrText);
  109.  
  110.   SendMessage(hwnd,SCI_SETUNDOCOLLECTION,1,0);
  111.   SendMessage(hwnd,EM_EMPTYUNDOBUFFER,0,0);
  112.   SendMessage(hwnd,SCI_SETSAVEPOINT,0,0);
  113.   SendMessage(hwnd,SCI_GOTOPOS,0,0);
  114.   SendMessage(hwnd,SCI_CHOOSECARETX,0,0);
  115.  
  116. }
  117.  
  118.  
  119. //=============================================================================
  120. //
  121. //  EditDetectEOLMode() - moved here to handle Unicode files correctly
  122. //
  123. int EditDetectEOLMode(HWND hwnd,LPCSTR lpData,DWORD cbData)
  124. {
  125.   int iEOLMode = SC_EOL_CRLF;
  126.  
  127.   char *cp = lpData;
  128.   while (*cp && (*cp != '\x0D' && *cp != '\x0A')) cp++;
  129.  
  130.   if (*cp == '\x0D' && *(cp+1) != '\x0A')
  131.     iEOLMode = SC_EOL_CR;
  132.   else if (*cp == '\x0A')
  133.     iEOLMode = SC_EOL_LF;
  134.  
  135.   return (iEOLMode);
  136. }
  137.  
  138.  
  139.  
  140. //=============================================================================
  141. //
  142. //  IsUnicode(), IsUTF8(), IsUTF7()
  143. //
  144. BOOL IsUnicode(const char* pBuffer,int cb,LPBOOL lpbBOM,LPBOOL lpbReverse)
  145. {
  146.  
  147.   int i = 0xFFFF;
  148.  
  149.   BOOL bIsTextUnicode;
  150.  
  151.   BOOL bHasBOM;
  152.   BOOL bHasRBOM;
  153.  
  154.   if (!pBuffer || cb < 2)
  155.     return FALSE;
  156.  
  157.   bIsTextUnicode = IsTextUnicode(pBuffer,cb,&i);
  158.  
  159.   bHasBOM  = (*pBuffer == '\xFF' && *(pBuffer+1) == '\xFE');
  160.   bHasRBOM = (*pBuffer == '\xFE' && *(pBuffer+1) == '\xFF');
  161.  
  162.   /*
  163.   #define IS_TEXT_UNICODE_ASCII16               0x0001
  164.   #define IS_TEXT_UNICODE_REVERSE_ASCII16       0x0010
  165.   #define IS_TEXT_UNICODE_STATISTICS            0x0002
  166.   #define IS_TEXT_UNICODE_REVERSE_STATISTICS    0x0020
  167.   #define IS_TEXT_UNICODE_CONTROLS              0x0004
  168.   #define IS_TEXT_UNICODE_REVERSE_CONTROLS      0x0040
  169.   #define IS_TEXT_UNICODE_SIGNATURE             0x0008
  170.   #define IS_TEXT_UNICODE_REVERSE_SIGNATURE     0x0080
  171.   #define IS_TEXT_UNICODE_ILLEGAL_CHARS         0x0100
  172.   #define IS_TEXT_UNICODE_ODD_LENGTH            0x0200
  173.   #define IS_TEXT_UNICODE_DBCS_LEADBYTE         0x0400
  174.   #define IS_TEXT_UNICODE_NULL_BYTES            0x1000
  175.   *//*
  176.   {
  177.     char szBuf[512];
  178.  
  179.     wsprintf(szBuf,
  180.       "IS_TEXT_UNICODE_ASCII16\t\t\t%s\n"\
  181.       "IS_TEXT_UNICODE_REVERSE_ASCII16\t\t%s\n"\
  182.       "IS_TEXT_UNICODE_STATISTICS\t\t%s\n"\
  183.       "IS_TEXT_UNICODE_REVERSE_STATISTICS\t%s\n"\
  184.       "IS_TEXT_UNICODE_CONTROLS\t\t%s\n"\
  185.       "IS_TEXT_UNICODE_REVERSE_CONTROLS\t%s\n"\
  186.       "IS_TEXT_UNICODE_SIGNATURE\t\t%s\n"\
  187.       "IS_TEXT_UNICODE_REVERSE_SIGNATURE\t%s\n"\
  188.       "IS_TEXT_UNICODE_ILLEGAL_CHARS\t\t%s\n"\
  189.       "IS_TEXT_UNICODE_ODD_LENGTH\t\t%s\n"\
  190.       "IS_TEXT_UNICODE_DBCS_LEADBYTE\t\t%s\n"\
  191.       "IS_TEXT_UNICODE_NULL_BYTES\t\t%s\n\n"\
  192.       "bIsTextUnicode\t\t\t\t%i\n\n"\
  193.       "bHasBOM\t\t\t\t\t%i\n"\
  194.       "bHasRBOM\t\t\t\t%i",
  195.       i & IS_TEXT_UNICODE_ASCII16 ? "1" :"-",
  196.       i & IS_TEXT_UNICODE_REVERSE_ASCII16 ? "1" :"-",
  197.       i & IS_TEXT_UNICODE_STATISTICS ? "1" :"-",
  198.       i & IS_TEXT_UNICODE_REVERSE_STATISTICS ? "1" :"-",
  199.       i & IS_TEXT_UNICODE_CONTROLS ? "1" :"-",
  200.       i & IS_TEXT_UNICODE_REVERSE_CONTROLS ? "1" :"-",
  201.       i & IS_TEXT_UNICODE_SIGNATURE ? "1" :"-",
  202.       i & IS_TEXT_UNICODE_REVERSE_SIGNATURE ? "1" :"-",
  203.       i & IS_TEXT_UNICODE_ILLEGAL_CHARS ? "1" :"-",
  204.       i & IS_TEXT_UNICODE_ODD_LENGTH ? "1" :"-",
  205.       i & IS_TEXT_UNICODE_DBCS_LEADBYTE ? "1" :"-",
  206.       i & IS_TEXT_UNICODE_NULL_BYTES ? "1" :"-",
  207.       bIsTextUnicode,bHasBOM,bHasRBOM);
  208.  
  209.     MessageBox(hwnd,szBuf,"Unicode file guessing",0);
  210.   }*/
  211.   /*
  212.   Andere Variante: IsTextUnicode() einmal auf normal, einmal auf _swab(),
  213.   wenn vorhanden BOM und RBOM selber entfernen
  214.  
  215.   Auch noch zu Probieren: Einfach konvertieren, und mit lpUsedDefaultChar
  216.   bei WideCharToMultiByte() checken, ob Zeichen nicht interpretiert werden
  217.   konnten -> Hinweis auf non-Unicode-File.
  218.   */
  219.  
  220.   if (i == 0xFFFF) // i doesn't seem to have been modified ...
  221.     i = 0;
  222.  
  223.   if (bIsTextUnicode || bHasBOM || bHasRBOM ||
  224.         ((i & (IS_TEXT_UNICODE_UNICODE_MASK | IS_TEXT_UNICODE_REVERSE_MASK)) &&
  225.        !((i & IS_TEXT_UNICODE_UNICODE_MASK) && (i & IS_TEXT_UNICODE_REVERSE_MASK)) &&
  226.         !(i & IS_TEXT_UNICODE_ODD_LENGTH) &&
  227.         !(i & IS_TEXT_UNICODE_ILLEGAL_CHARS && !(i & IS_TEXT_UNICODE_REVERSE_SIGNATURE)))) {
  228.  
  229.     if (lpbBOM)
  230.       *lpbBOM = (bHasBOM || bHasRBOM ||
  231.         (i & (IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE)))
  232.           ? TRUE : FALSE;
  233.  
  234.     if (lpbReverse)
  235.       *lpbReverse = (bHasRBOM || (i & IS_TEXT_UNICODE_REVERSE_MASK)) ? TRUE : FALSE;
  236.  
  237.     return TRUE;
  238.   }
  239.  
  240.   else
  241.  
  242.     return FALSE;
  243.  
  244. }
  245.  
  246.  
  247. BOOL IsUTF8(const char* pTest,int nLength)
  248. {
  249.   static int byte_class_table[256] = {
  250.   /*       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  */
  251.   /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  252.   /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  253.   /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  254.   /* 30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  255.   /* 40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  256.   /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  257.   /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  258.   /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  259.   /* 80 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  260.   /* 90 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  261.   /* A0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  262.   /* B0 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  263.   /* C0 */ 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  264.   /* D0 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  265.   /* E0 */ 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 7,
  266.   /* F0 */ 9,10,10,10,11, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  267.   /*       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  */ };
  268.  
  269.   /* state table */
  270.   typedef enum {
  271.     kSTART = 0,kA,kB,kC,kD,kE,kF,kG,kERROR,kNumOfStates } utf8_state;
  272.  
  273.   static utf8_state state_table[] = {
  274.   /*                            kSTART, kA,     kB,     kC,     kD,     kE,     kF,     kG,     kERROR */
  275.   /* 0x00-0x7F: 0            */ kSTART, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  276.   /* 0x80-0x8F: 1            */ kERROR, kSTART, kA,     kERROR, kA,     kB,     kERROR, kB,     kERROR,
  277.   /* 0x90-0x9f: 2            */ kERROR, kSTART, kA,     kERROR, kA,     kB,     kB,     kERROR, kERROR,
  278.   /* 0xa0-0xbf: 3            */ kERROR, kSTART, kA,     kA,     kERROR, kB,     kB,     kERROR, kERROR,
  279.   /* 0xc0-0xc1, 0xf5-0xff: 4 */ kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  280.   /* 0xc2-0xdf: 5            */ kA,     kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  281.   /* 0xe0: 6                 */ kC,     kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  282.   /* 0xe1-0xec, 0xee-0xef: 7 */ kB,     kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  283.   /* 0xed: 8                 */ kD,     kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  284.   /* 0xf0: 9                 */ kF,     kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  285.   /* 0xf1-0xf3: 10           */ kE,     kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR,
  286.   /* 0xf4: 11                */ kG,     kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR, kERROR };
  287.  
  288.   #define BYTE_CLASS(b) (byte_class_table[(unsigned char)b])
  289.   #define NEXT_STATE(b,cur) (state_table[(BYTE_CLASS(b) * kNumOfStates) + (cur)])
  290.  
  291.     utf8_state current = kSTART;
  292.     int i;
  293.  
  294.     const char* pt = pTest;
  295.     int len = nLength;
  296.  
  297.     for(i = 0; i < len ; i++, pt++) {
  298.  
  299.       current = NEXT_STATE(*pt,current);
  300.       if (kERROR == current)
  301.         break; }
  302.  
  303.     return (current == kSTART) ? TRUE : FALSE;
  304.   }
  305.  
  306.  
  307. BOOL IsUTF7(const char* pTest,int nLength)
  308. {
  309.   int i;
  310.   const char *pt = pTest;
  311.  
  312.   for (i = 0; i < nLength; i++) {
  313.     if (*pt & 0x80 || !*pt)
  314.       return FALSE;
  315.     pt++; }
  316.  
  317.   return TRUE;
  318. }
  319.  
  320.  
  321. #define IsUTF8Signature(p) \
  322.           ((*(p+0) == '\xEF' && *(p+1) == '\xBB' && *(p+2) == '\xBF'))
  323.  
  324.  
  325. #define UTF8StringStart(p) \
  326.           (IsUTF8Signature(p)) ? (p+3) : (p)
  327.  
  328.  
  329. /* byte length of UTF-8 sequence based on value of first byte.
  330.    for UTF-16 (21-bit space), max. code length is 4, so we only need to look
  331.    at 4 upper bits.
  332.  */
  333. static const INT utf8_lengths[16]=
  334. {
  335.     1,1,1,1,1,1,1,1,        /* 0000 to 0111 : 1 byte (plain ASCII) */
  336.     0,0,0,0,                /* 1000 to 1011 : not valid */
  337.     2,2,                    /* 1100, 1101 : 2 bytes */
  338.     3,                      /* 1110 : 3 bytes */
  339.     4                       /* 1111 :4 bytes */
  340. };
  341.  
  342. /*++
  343. Function :
  344.     UTF8_mbslen_bytes [INTERNAL]
  345.  
  346.     Calculates the byte size of a NULL-terminated UTF-8 string.
  347.  
  348. Parameters :
  349.     char *utf8_string : string to examine
  350.  
  351. Return value :
  352.     size (in bytes) of a NULL-terminated UTF-8 string.
  353.     -1 if invalid NULL-terminated UTF-8 string
  354. --*/
  355. static INT UTF8_mbslen_bytes(LPCSTR utf8_string)
  356. {
  357.     INT length=0;
  358.     INT code_size;
  359.     BYTE byte;
  360.  
  361.     while(*utf8_string)
  362.     {
  363.         byte=(BYTE)*utf8_string;
  364.  
  365.         if( (byte <= 0xF7) && (0 != (code_size = utf8_lengths[ byte >> 4 ])))
  366.         {
  367.             length+=code_size;
  368.             utf8_string+=code_size;
  369.         }
  370.         else
  371.         {
  372.             /* we got an invalid byte value but need to count it,
  373.                it will be later ignored during the string conversion */
  374.             //WARN("invalid first byte value 0x%02X in UTF-8 sequence!\n",byte);
  375.             length++;
  376.             utf8_string++;
  377.         }
  378.     }
  379.     length++; /* include NULL terminator */
  380.     return length;
  381. }
  382.  
  383. /*++
  384. Function :
  385.     UTF8_mbslen [INTERNAL]
  386.  
  387.     Calculates the character size of a NULL-terminated UTF-8 string.
  388.  
  389. Parameters :
  390.     char *utf8_string : string to examine
  391.     int byte_length : byte size of string
  392.  
  393. Return value :
  394.     size (in characters) of a UTF-8 string.
  395.     -1 if invalid UTF-8 string
  396. --*/
  397. static INT UTF8_mbslen(LPCSTR source, INT byte_length)
  398. {
  399.     INT wchar_length=0;
  400.     INT code_size;
  401.     BYTE byte;
  402.  
  403.     while(byte_length > 0)
  404.     {
  405.         byte=(BYTE)*source;
  406.  
  407.         /* UTF-16 can't encode 5-byte and 6-byte sequences, so maximum value
  408.            for first byte is 11110111. Use lookup table to determine sequence
  409.            length based on upper 4 bits of first byte */
  410.         if ((byte <= 0xF7) && (0 != (code_size=utf8_lengths[ byte >> 4])))
  411.         {
  412.             /* 1 sequence == 1 character */
  413.             wchar_length++;
  414.  
  415.             if(code_size==4)
  416.                 wchar_length++;
  417.  
  418.             source+=code_size;        /* increment pointer */
  419.             byte_length-=code_size;   /* decrement counter*/
  420.         }
  421.         else
  422.         {
  423.             /*
  424.                unlike UTF8_mbslen_bytes, we ignore the invalid characters.
  425.                we only report the number of valid characters we have encountered
  426.                to match the Windows behavior.
  427.             */
  428.             //WARN("invalid byte 0x%02X in UTF-8 sequence, skipping it!\n",
  429.             //     byte);
  430.             source++;
  431.             byte_length--;
  432.         }
  433.     }
  434.     return wchar_length;
  435. }
  436.  
  437.  
  438. //=============================================================================
  439. //
  440. //  EditLoadFile()
  441. //
  442. BOOL EditLoadFile(HWND hwnd,LPCSTR pszFile,BOOL bSkipEncodingDetection,
  443.                   int* iCodePage,int* iEOLMode,BOOL *pbUnicodeErr,BOOL *pbFileTooBig)
  444. {
  445.  
  446.   HANDLE hFile;
  447.  
  448.   DWORD  dwFileSize;
  449.   DWORD  dwFileSizeLimit;
  450.   DWORD  dwBufSize;
  451.   BOOL   bReadSuccess;
  452.  
  453.   LPSTR lpData;
  454.   DWORD cbData;
  455.   //char  *cp;
  456.  
  457.   BOOL bBOM;
  458.   BOOL bReverse;
  459.  
  460.   *pbUnicodeErr = FALSE;
  461.   *pbFileTooBig = FALSE;
  462.  
  463.   hFile = CreateFile(pszFile,
  464.                      GENERIC_READ,
  465.                      FILE_SHARE_READ|FILE_SHARE_WRITE,
  466.                      NULL,
  467.                      OPEN_EXISTING,
  468.                      FILE_ATTRIBUTE_NORMAL,
  469.                      NULL);
  470.  
  471.   if (hFile == INVALID_HANDLE_VALUE)
  472.     return FALSE;
  473.  
  474.   // calculate buffer limit
  475.   dwFileSize = GetFileSize(hFile,NULL);
  476.   dwBufSize  = dwFileSize + 10;
  477.  
  478.   // Check if a warning message should be displayed for large files
  479.   dwFileSizeLimit = RegGetAppIntEx("Settings","FileLoadWarningMB",1);
  480.   if (dwFileSizeLimit != 0 && dwFileSizeLimit * 1024 * 1024 < dwFileSize) {
  481.     if (MsgBox(MBYESNOWARN,IDS_WARNLOADBIGFILE) != IDYES) {
  482.       CloseHandle(hFile);
  483.       *pbFileTooBig = TRUE;
  484.       return FALSE;
  485.     }
  486.   }
  487.  
  488.   lpData = GlobalAlloc(GPTR,dwBufSize);
  489.   bReadSuccess = ReadFile(hFile,lpData,GlobalSize(lpData)-2,&cbData,NULL);
  490.   CloseHandle(hFile);
  491.  
  492.   if (!bReadSuccess)
  493.   {
  494.     GlobalFree(lpData);
  495.     return FALSE;
  496.   }
  497.  
  498.   // default codepage
  499.   *iCodePage = NCP_DEFAULT;
  500.  
  501.   if (!bSkipEncodingDetection &&
  502.       IsUnicode(lpData,cbData,&bBOM,&bReverse) && !IsUTF8Signature(lpData)) // check for UTF-8 signature
  503.   {
  504.     LPSTR  lpDataUTF8;
  505.     CPINFO cpi;
  506.     UINT   uCP_UTF8;
  507.  
  508.     *iCodePage = NCP_UNICODE;
  509.     if (bBOM)
  510.       *iCodePage |= NCP_UNICODE_BOM;
  511.  
  512.     if (bReverse)
  513.     {
  514.       _swab(lpData,lpData,cbData);
  515.       *iCodePage |= NCP_UNICODE_REVERSE;
  516.     }
  517.  
  518.     // Unicode text is converted to ANSI and not to UTF-8 on Windows 95
  519.     uCP_UTF8 = (GetCPInfo(CP_UTF8, &cpi) || IsValidCodePage(CP_UTF8)) ? CP_UTF8 : CP_ACP;
  520.  
  521.     lpDataUTF8 = GlobalAlloc(GPTR,(cbData * 3) + 2);
  522.     cbData = WideCharToMultiByte(uCP_UTF8,0,(bBOM) ? (LPWSTR)lpData + 1 : (LPWSTR)lpData,
  523.               (-1),lpDataUTF8,GlobalSize(lpDataUTF8),NULL,NULL);
  524.  
  525.     if (cbData == 0 && uCP_UTF8 == CP_UTF8)
  526.     {
  527.       cbData = WideCharToMultiByte(CP_ACP,0,(bBOM) ? (LPWSTR)lpData + 1 : (LPWSTR)lpData,
  528.                 (-1),lpDataUTF8,GlobalSize(lpDataUTF8),NULL,NULL);
  529.       *pbUnicodeErr = TRUE;
  530.     }
  531.  
  532.     GlobalFree(lpData);
  533.     SendMessage(hwnd,SCI_SETCODEPAGE,SC_CP_UTF8,0);
  534.     EditSetNewText(hwnd,"",0);
  535.     EditSetNewText(hwnd,lpDataUTF8,cbData-1);
  536.     *iEOLMode = EditDetectEOLMode(hwnd,lpDataUTF8,cbData-1);
  537.     GlobalFree(lpDataUTF8);
  538.   }
  539.  
  540.   else if (!bSkipEncodingDetection &&
  541.            IsUTF8(lpData,cbData) &&
  542.            ((UTF8_mbslen_bytes(UTF8StringStart(lpData)) - 1 !=
  543.              UTF8_mbslen(UTF8StringStart(lpData),IsUTF8Signature(lpData) ? cbData-3 : cbData)) ||
  544.              IsUTF8Signature(lpData)))
  545.   {
  546.     SendMessage(hwnd,SCI_SETCODEPAGE,SC_CP_UTF8,0);
  547.     EditSetNewText(hwnd,"",0);
  548.     if (IsUTF8Signature(lpData)) {
  549.       EditSetNewText(hwnd,UTF8StringStart(lpData),cbData-3);
  550.       *iEOLMode = EditDetectEOLMode(hwnd,UTF8StringStart(lpData),cbData-3);
  551.       *iCodePage = NCP_UTF8 | NCP_UTF8_SIGN; }
  552.     else {
  553.       EditSetNewText(hwnd,lpData,cbData);
  554.       *iEOLMode = EditDetectEOLMode(hwnd,lpData,cbData);
  555.       *iCodePage = NCP_UTF8; }
  556.     GlobalFree(lpData);
  557.   }
  558.  
  559.   else
  560.   {
  561.     SendMessage(hwnd,SCI_SETCODEPAGE,iDefaultCodePage,0);
  562.     EditSetNewText(hwnd,"",0);
  563.     EditSetNewText(hwnd,lpData,cbData);
  564.     *iEOLMode = EditDetectEOLMode(hwnd,lpData,cbData);
  565.     *iCodePage = NCP_DEFAULT;
  566.     GlobalFree(lpData);
  567.   }
  568.  
  569.   return TRUE;
  570.  
  571. }
  572.  
  573.  
  574. //=============================================================================
  575. //
  576. //  EditSaveFile()
  577. //
  578. BOOL EditSaveFile(HWND hwnd,LPCSTR pszFile,int iCodePage,BOOL bSaveCopy)
  579. {
  580.  
  581.   HANDLE hFile;
  582.   BOOL   bWriteSuccess;
  583.  
  584.   LPSTR lpData;
  585.   DWORD cbData;
  586.   DWORD dwBytesWritten;
  587.  
  588.   hFile = CreateFile(pszFile,
  589.                      GENERIC_WRITE,
  590.                      FILE_SHARE_READ|FILE_SHARE_WRITE,
  591.                      NULL,
  592.                      CREATE_ALWAYS,
  593.                      FILE_ATTRIBUTE_NORMAL,
  594.                      NULL);
  595.  
  596.   // failure could be due to missing attributes (2k/XP)
  597.   if (hFile == INVALID_HANDLE_VALUE)
  598.   {
  599.     DWORD dwAttributes = GetFileAttributes(pszFile);
  600.     if (dwAttributes != INVALID_FILE_ATTRIBUTES)
  601.     {
  602.       dwAttributes = dwAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
  603.       hFile = CreateFile(pszFile,
  604.                         GENERIC_WRITE,
  605.                         FILE_SHARE_READ|FILE_SHARE_WRITE,
  606.                         NULL,
  607.                         CREATE_ALWAYS,
  608.                         FILE_ATTRIBUTE_NORMAL | dwAttributes,
  609.                         NULL);
  610.     }
  611.   }
  612.  
  613.   if (hFile == INVALID_HANDLE_VALUE)
  614.     return FALSE;
  615.  
  616.   // get text
  617.   cbData = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  618.   lpData = GlobalAlloc(GPTR,cbData + 1);
  619.   SendMessage(hwnd,SCI_GETTEXT,GlobalSize(lpData),(LPARAM)lpData);
  620.  
  621.   if (cbData == 0)
  622.     bWriteSuccess = SetEndOfFile(hFile);
  623.  
  624.   else
  625.   {
  626.  
  627.     if (iCodePage & NCP_UNICODE)
  628.     {
  629.       LPWSTR lpDataWide;
  630.       int    cbDataWide;
  631.       CPINFO cpi;
  632.       UINT   uCP_UTF8;
  633.  
  634.       // UTF-8 text is interpreted as ANSI when saving as Unicode on Windows 95
  635.       uCP_UTF8 = (GetCPInfo(CP_UTF8, &cpi) || IsValidCodePage(CP_UTF8)) ? CP_UTF8 : CP_ACP;
  636.  
  637.       lpDataWide = GlobalAlloc(GPTR,cbData * 2 + 16);
  638.       cbDataWide = MultiByteToWideChar(uCP_UTF8,0,lpData,cbData,lpDataWide,GlobalSize(lpDataWide));
  639.  
  640.       if (iCodePage & NCP_UNICODE_BOM) {
  641.         if (iCodePage & NCP_UNICODE_REVERSE)
  642.           WriteFile(hFile,(LPCVOID)"\xFE\xFF",2,&dwBytesWritten,NULL);
  643.         else
  644.           WriteFile(hFile,(LPCVOID)"\xFF\xFE",2,&dwBytesWritten,NULL); }
  645.  
  646.       if (iCodePage & NCP_UNICODE_REVERSE)
  647.         _swab((char*)lpDataWide,(char*)lpDataWide,cbDataWide * sizeof(WCHAR));
  648.  
  649.       bWriteSuccess = WriteFile(hFile,lpDataWide,cbDataWide * sizeof(WCHAR),&dwBytesWritten,NULL);
  650.  
  651.       GlobalFree(lpData);
  652.     }
  653.  
  654.     else if (iCodePage & NCP_UTF8)
  655.     {
  656.       if (iCodePage & NCP_UTF8_SIGN)
  657.         WriteFile(hFile,(LPCVOID)"\xEF\xBB\xBF",3,&dwBytesWritten,NULL);
  658.  
  659.       bWriteSuccess = WriteFile(hFile,lpData,cbData,&dwBytesWritten,NULL);
  660.     }
  661.  
  662.     else // convert text to 8bit
  663.     {
  664.       //LPWSTR lpDataWide = GlobalAlloc(GPTR,cbData * 2 + 16);
  665.       //int    cbDataWide = MultiByteToWideChar(CP_UTF8,0,lpData,cbData,lpDataWide,GlobalSize(lpDataWide));
  666.  
  667.       //ZeroMemory(lpData,GlobalSize(lpData));
  668.       //cbData = WideCharToMultiByte(CP_ACP,0,lpDataWide,cbDataWide,lpData,GlobalSize(lpData),NULL,NULL);
  669.       //GlobalFree(lpDataWide);
  670.  
  671.       bWriteSuccess = WriteFile(hFile,lpData,cbData,&dwBytesWritten,NULL);
  672.  
  673.       GlobalFree(lpData);
  674.     }
  675.   }
  676.  
  677.   CloseHandle(hFile);
  678.  
  679.   if (bWriteSuccess)
  680.   {
  681.     if (!bSaveCopy)
  682.       SendMessage(hwnd,SCI_SETSAVEPOINT,0,0);
  683.  
  684.     return TRUE;
  685.   }
  686.  
  687.   else
  688.     return FALSE;
  689.  
  690. }
  691.  
  692.  
  693. //=============================================================================
  694. //
  695. //  EditMakeUppercase()
  696. //
  697. void EditMakeUppercase(HWND hwnd)
  698. {
  699.   int cchTextW;
  700.   int iCurPos;
  701.   int iAnchorPos;
  702.   UINT cpEdit;
  703.   int i;
  704.   BOOL bChanged = FALSE;
  705.  
  706.   if (!IsWindowsNT())
  707.   {
  708.     SendMessage(hwnd,SCI_UPPERCASE,0,0);
  709.     return;
  710.   }
  711.  
  712.   iCurPos    = SendMessage(hwnd,SCI_GETCURRENTPOS,0,0);
  713.   iAnchorPos = SendMessage(hwnd,SCI_GETANCHOR,0,0);
  714.  
  715.   if (iCurPos != iAnchorPos)
  716.   {
  717.     if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  718.     {
  719.       int iSelCount = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) -
  720.                         SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);
  721.  
  722.       LPSTR  pszText  = GlobalAlloc(GPTR,(iSelCount)+2);
  723.       LPWSTR pszTextW = GlobalAlloc(GPTR,(iSelCount*2)+2);
  724.  
  725.       if (pszText == NULL || pszTextW == NULL) {
  726.         GlobalFree(pszText);
  727.         GlobalFree(pszTextW);
  728.         return; }
  729.  
  730.       SendMessage(hwnd,SCI_GETSELTEXT,0,(LPARAM)pszText);
  731.  
  732.       cpEdit = SendMessage(hwnd,SCI_GETCODEPAGE,0,0);
  733.  
  734.       cchTextW = MultiByteToWideChar(cpEdit,0,pszText,iSelCount,pszTextW,GlobalSize(pszTextW) / sizeof(WCHAR));
  735.  
  736.       for (i = 0; i < cchTextW; i++) {
  737.         if (IsCharLowerW(pszTextW[i])) {
  738.           pszTextW[i] = LOWORD(CharUpperW((LPWSTR)MAKELONG(pszTextW[i],0)));
  739.           bChanged = TRUE; } }
  740.  
  741.       if (bChanged) {
  742.  
  743.         WideCharToMultiByte(cpEdit,0,pszTextW,cchTextW,pszText,GlobalSize(pszText),NULL,NULL);
  744.         GlobalFree(pszTextW);
  745.  
  746.         SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  747.         SendMessage(hwnd,SCI_CLEAR,0,0);
  748.         SendMessage(hwnd,SCI_ADDTEXT,(WPARAM)iSelCount,(LPARAM)pszText);
  749.         SendMessage(hwnd,SCI_SETSEL,(WPARAM)iAnchorPos,(LPARAM)iCurPos);
  750.         SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  751.  
  752.         GlobalFree(pszText); }
  753.  
  754.       else
  755.         GlobalFree(pszTextW);
  756.  
  757.     }
  758.     else
  759.       MsgBox(MBINFO,IDS_SELRECT);
  760.   }
  761. }
  762.  
  763.  
  764. //=============================================================================
  765. //
  766. //  EditMakeLowercase()
  767. //
  768. void EditMakeLowercase(HWND hwnd)
  769. {
  770.   int cchTextW;
  771.   int iCurPos;
  772.   int iAnchorPos;
  773.   UINT cpEdit;
  774.   int i;
  775.   BOOL bChanged = FALSE;
  776.  
  777.   if (!IsWindowsNT())
  778.   {
  779.     SendMessage(hwnd,SCI_LOWERCASE,0,0);
  780.     return;
  781.   }
  782.  
  783.   iCurPos    = SendMessage(hwnd,SCI_GETCURRENTPOS,0,0);
  784.   iAnchorPos = SendMessage(hwnd,SCI_GETANCHOR,0,0);
  785.  
  786.   if (iCurPos != iAnchorPos)
  787.   {
  788.     if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  789.     {
  790.       int iSelCount = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) -
  791.                         SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);
  792.  
  793.       LPSTR  pszText  = GlobalAlloc(GPTR,(iSelCount)+2);
  794.       LPWSTR pszTextW = GlobalAlloc(GPTR,(iSelCount*2)+2);
  795.  
  796.       if (pszText == NULL || pszTextW == NULL) {
  797.         GlobalFree(pszText);
  798.         GlobalFree(pszTextW);
  799.         return; }
  800.  
  801.       SendMessage(hwnd,SCI_GETSELTEXT,0,(LPARAM)pszText);
  802.  
  803.       cpEdit = SendMessage(hwnd,SCI_GETCODEPAGE,0,0);
  804.  
  805.       cchTextW = MultiByteToWideChar(cpEdit,0,pszText,iSelCount,pszTextW,GlobalSize(pszTextW) / sizeof(WCHAR));
  806.  
  807.       for (i = 0; i < cchTextW; i++) {
  808.         if (IsCharUpperW(pszTextW[i])) {
  809.           pszTextW[i] = LOWORD(CharLowerW((LPWSTR)MAKELONG(pszTextW[i],0)));
  810.           bChanged = TRUE; } }
  811.  
  812.       if (bChanged) {
  813.  
  814.         WideCharToMultiByte(cpEdit,0,pszTextW,cchTextW,pszText,GlobalSize(pszText),NULL,NULL);
  815.         GlobalFree(pszTextW);
  816.  
  817.         SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  818.         SendMessage(hwnd,SCI_CLEAR,0,0);
  819.         SendMessage(hwnd,SCI_ADDTEXT,(WPARAM)iSelCount,(LPARAM)pszText);
  820.         SendMessage(hwnd,SCI_SETSEL,(WPARAM)iAnchorPos,(LPARAM)iCurPos);
  821.         SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  822.  
  823.         GlobalFree(pszText); }
  824.  
  825.       else
  826.         GlobalFree(pszTextW);
  827.  
  828.     }
  829.     else
  830.       MsgBox(MBINFO,IDS_SELRECT);
  831.   }
  832. }
  833.  
  834.  
  835. //=============================================================================
  836. //
  837. //  EditTabsToSpaces()
  838. //
  839. void EditTabsToSpaces(HWND hwnd,int nTabWidth)
  840. {
  841.   if (!IsWindowsNT())
  842.   {
  843.     int i;
  844.     EDITFINDREPLACE efrTTS = { "\t", "", "", "", SCFIND_REGEXP, 0, 0, 0, hwnd };
  845.  
  846.     for (i = 0; i < nTabWidth; i++)
  847.       efrTTS.szReplace[i] = ' ';
  848.     efrTTS.szReplace[nTabWidth] = 0;
  849.  
  850.     // Check if there is any selection... simply use a regular expression replace!
  851.     if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) - SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0))
  852.     {
  853.       if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  854.         EditReplaceAllInSelection(hwnd,&efrTTS,FALSE);
  855.  
  856.       else
  857.         MsgBox(MBINFO,IDS_SELRECT);
  858.     }
  859.     else
  860.       /*EditReplaceAll(hwnd,&efrTTS,FALSE)*/;
  861.   }
  862.  
  863.   else
  864.   {
  865.     LPSTR pszText;
  866.     LPWSTR pszTextW;
  867.     int cchTextW;
  868.     int iTextW;
  869.     LPWSTR pszConvW;
  870.     int cchConvW;
  871.     int cchConvM;
  872.     int i,j;
  873.     int iLine;
  874.     int iCurPos;
  875.     int iAnchorPos;
  876.     int iSelStart;
  877.     int iSelEnd;
  878.     int iSelCount;
  879.     UINT cpEdit;
  880.     struct TextRange tr;
  881.  
  882.     if (SC_SEL_RECTANGLE == SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0)) {
  883.       MsgBox(MBINFO,IDS_SELRECT);
  884.       return; }
  885.  
  886.     iCurPos    = SendMessage(hwnd,SCI_GETCURRENTPOS,0,0);
  887.     iAnchorPos = SendMessage(hwnd,SCI_GETANCHOR,0,0);
  888.  
  889.     if (iCurPos == iAnchorPos) /*{
  890.       iSelStart = 0;
  891.       iSelEnd   = SendMessage(hwnd,SCI_GETLENGTH,0,0); }*/
  892.       return;
  893.  
  894.     else {
  895.       iSelStart = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);
  896.       iSelEnd   = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); }
  897.  
  898.     iLine = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iSelStart,0);
  899.     iSelStart = SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0);
  900.  
  901.     iSelCount = iSelEnd - iSelStart;
  902.  
  903.     pszText = GlobalAlloc(GPTR,(iSelCount)+2);
  904.     if (pszText == NULL)
  905.       return;
  906.  
  907.     pszTextW = GlobalAlloc(GPTR,(iSelCount*2)+2);
  908.     if (pszTextW == NULL) {
  909.       GlobalFree(pszText);
  910.       return; }
  911.  
  912.     tr.chrg.cpMin = iSelStart;
  913.     tr.chrg.cpMax = iSelEnd;
  914.     tr.lpstrText = pszText;
  915.     SendMessage(hwnd,SCI_GETTEXTRANGE,0,(LPARAM)&tr);
  916.  
  917.     cpEdit = SendMessage(hwnd,SCI_GETCODEPAGE,0,0);
  918.  
  919.     cchTextW = MultiByteToWideChar(cpEdit,0,pszText,iSelCount,pszTextW,GlobalSize(pszTextW) / sizeof(WCHAR));
  920.     GlobalFree(pszText);
  921.  
  922.     pszConvW = GlobalAlloc(GPTR,cchTextW*sizeof(WCHAR)*nTabWidth+2);
  923.     if (pszConvW == NULL) {
  924.       GlobalFree(pszTextW);
  925.       return; }
  926.  
  927.     cchConvW = 0;
  928.  
  929.     // Contributed by Homam
  930.     // Thank you very much!
  931.     i=0;
  932.     for (iTextW = 0; iTextW < cchTextW; iTextW++)
  933.     {
  934.       WCHAR w = pszTextW[iTextW];
  935.       if (w == L'\t') {
  936.         for (j = 0; j < nTabWidth - i % nTabWidth; j++)
  937.           pszConvW[cchConvW++] = L' ';
  938.         i = 0;
  939.       }
  940.       else {
  941.         i++;
  942.         if (w == L'\n' || w == L'\r')
  943.           i = 0;
  944.         pszConvW[cchConvW++] = w;
  945.       }
  946.     }
  947.  
  948.     GlobalFree(pszTextW);
  949.  
  950.     if (cchConvW != cchTextW) {
  951.       pszText = GlobalAlloc(GPTR,cchConvW * 3);
  952.  
  953.       cchConvM = WideCharToMultiByte(cpEdit,0,pszConvW,cchConvW,pszText,GlobalSize(pszText),NULL,NULL);
  954.       GlobalFree(pszConvW);
  955.  
  956.       if (iAnchorPos > iCurPos) {
  957.         iCurPos = iSelStart;
  958.         iAnchorPos = iSelStart + cchConvM; }
  959.       else {
  960.         iAnchorPos = iSelStart;
  961.         iCurPos = iSelStart + cchConvM; }
  962.  
  963.       SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  964.       SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iSelStart,0);
  965.       SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iSelEnd,0);
  966.       SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)cchConvM,(LPARAM)pszText);
  967.       //SendMessage(hwnd,SCI_CLEAR,0,0);
  968.       //SendMessage(hwnd,SCI_ADDTEXT,(WPARAM)cchConvW,(LPARAM)pszText);
  969.       SendMessage(hwnd,SCI_SETSEL,(WPARAM)iAnchorPos,(LPARAM)iCurPos);
  970.       SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  971.  
  972.       GlobalFree(pszText); }
  973.  
  974.     else
  975.       GlobalFree(pszConvW);
  976.   }
  977. }
  978.  
  979.  
  980. //=============================================================================
  981. //
  982. //  EditSpacesToTabs()
  983. //
  984. void EditSpacesToTabs(HWND hwnd,int nTabWidth)
  985. {
  986.   if (!IsWindowsNT())
  987.   {
  988.     int i;
  989.     EDITFINDREPLACE efrSTT = { "", "\t", "", "", SCFIND_REGEXP, 0, 0, 0, hwnd };
  990.  
  991.     for (i = 0; i < nTabWidth; i++)
  992.       efrSTT.szFind[i] = ' ';
  993.     efrSTT.szFind[nTabWidth] = 0;
  994.  
  995.     // Check if there is any selection... simply use a regular expression replace!
  996.     if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) - SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0))
  997.     {
  998.       if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  999.         EditReplaceAllInSelection(hwnd,&efrSTT,FALSE);
  1000.  
  1001.       else
  1002.         MsgBox(MBINFO,IDS_SELRECT);
  1003.     }
  1004.     else
  1005.       /*EditReplaceAll(hwnd,&efrSTT,FALSE)*/;
  1006.   }
  1007.  
  1008.   else
  1009.   {
  1010.     LPSTR pszText;
  1011.     LPWSTR pszTextW;
  1012.     int cchTextW;
  1013.     int iTextW;
  1014.     LPWSTR pszConvW;
  1015.     int cchConvW;
  1016.     int cchConvM;
  1017.     int i,j,t;
  1018.     int iLine;
  1019.     int iCurPos;
  1020.     int iAnchorPos;
  1021.     int iSelStart;
  1022.     int iSelEnd;
  1023.     int iSelCount;
  1024.     UINT cpEdit;
  1025.     struct TextRange tr;
  1026.     WCHAR space[64];
  1027.  
  1028.     if (SC_SEL_RECTANGLE == SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0)) {
  1029.       MsgBox(MBINFO,IDS_SELRECT);
  1030.       return; }
  1031.  
  1032.     iCurPos    = SendMessage(hwnd,SCI_GETCURRENTPOS,0,0);
  1033.     iAnchorPos = SendMessage(hwnd,SCI_GETANCHOR,0,0);
  1034.  
  1035.     if (iCurPos == iAnchorPos) /*{
  1036.       iSelStart = 0;
  1037.       iSelEnd   = SendMessage(hwnd,SCI_GETLENGTH,0,0); }*/
  1038.       return;
  1039.  
  1040.     else {
  1041.       iSelStart = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);
  1042.       iSelEnd   = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0); }
  1043.  
  1044.     iLine = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iSelStart,0);
  1045.     iSelStart = SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0);
  1046.  
  1047.     iSelCount = iSelEnd - iSelStart;
  1048.  
  1049.     pszText = GlobalAlloc(GPTR,(iSelCount)+2);
  1050.     if (pszText == NULL)
  1051.       return;
  1052.  
  1053.     pszTextW = GlobalAlloc(GPTR,(iSelCount*2)+2);
  1054.     if (pszTextW == NULL) {
  1055.       GlobalFree(pszText);
  1056.       return; }
  1057.  
  1058.     tr.chrg.cpMin = iSelStart;
  1059.     tr.chrg.cpMax = iSelEnd;
  1060.     tr.lpstrText = pszText;
  1061.     SendMessage(hwnd,SCI_GETTEXTRANGE,0,(LPARAM)&tr);
  1062.  
  1063.     cpEdit = SendMessage(hwnd,SCI_GETCODEPAGE,0,0);
  1064.  
  1065.     cchTextW = MultiByteToWideChar(cpEdit,0,pszText,iSelCount,pszTextW,GlobalSize(pszTextW) / sizeof(WCHAR));
  1066.     GlobalFree(pszText);
  1067.  
  1068.     pszConvW = GlobalAlloc(GPTR,cchTextW*sizeof(WCHAR)+2);
  1069.     if (pszConvW == NULL) {
  1070.       GlobalFree(pszTextW);
  1071.       return; }
  1072.  
  1073.     cchConvW = 0;
  1074.  
  1075.     // Contributed by Homam
  1076.     // Thank you very much!
  1077.     i = j = 0;
  1078.     for (iTextW = 0; iTextW < cchTextW; iTextW++)
  1079.     {
  1080.       WCHAR w = pszTextW[iTextW];
  1081.       if ((w == L' ' || w == L'\t')) {
  1082.         space[j++] = w;
  1083.         if (j == nTabWidth - i % nTabWidth || w == L'\t') {
  1084.           if (j > 1 || pszTextW[iTextW+1] == L' ' || pszTextW[iTextW+1] == L'\t')
  1085.             pszConvW[cchConvW++] = L'\t';
  1086.           else
  1087.             pszConvW[cchConvW++] = w;
  1088.           i = j = 0;
  1089.         }
  1090.       }
  1091.       else {
  1092.         i += j + 1;
  1093.         if (j > 0) {
  1094.           //space[j] = '\0';
  1095.           for (t = 0; t < j; t++)
  1096.             pszConvW[cchConvW++] = space[t];
  1097.           j = 0;
  1098.         }
  1099.         if (w == L'\n' || w == L'\r')
  1100.           i = 0;
  1101.         pszConvW[cchConvW++] = w;
  1102.       }
  1103.     }
  1104.     if (j > 0) {
  1105.       for (t = 0; t < j; t++)
  1106.         pszConvW[cchConvW++] = space[t]; }
  1107.  
  1108.     GlobalFree(pszTextW);
  1109.  
  1110.     if (cchConvW != cchTextW) {
  1111.       pszText = GlobalAlloc(GPTR,cchConvW * 3);
  1112.  
  1113.       cchConvM = WideCharToMultiByte(cpEdit,0,pszConvW,cchConvW,pszText,GlobalSize(pszText),NULL,NULL);
  1114.       GlobalFree(pszConvW);
  1115.  
  1116.       if (iAnchorPos > iCurPos) {
  1117.         iCurPos = iSelStart;
  1118.         iAnchorPos = iSelStart + cchConvM; }
  1119.       else {
  1120.         iAnchorPos = iSelStart;
  1121.         iCurPos = iSelStart + cchConvM; }
  1122.  
  1123.       SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  1124.       SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iSelStart,0);
  1125.       SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iSelEnd,0);
  1126.       SendMessage(hwnd,SCI_REPLACETARGET,(WPARAM)cchConvM,(LPARAM)pszText);
  1127.       //SendMessage(hwnd,SCI_CLEAR,0,0);
  1128.       //SendMessage(hwnd,SCI_ADDTEXT,(WPARAM)cchConvW,(LPARAM)pszText);
  1129.       SendMessage(hwnd,SCI_SETSEL,(WPARAM)iAnchorPos,(LPARAM)iCurPos);
  1130.       SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  1131.  
  1132.       GlobalFree(pszText); }
  1133.  
  1134.     else
  1135.       GlobalFree(pszConvW);
  1136.   }
  1137. }
  1138.  
  1139.  
  1140. //=============================================================================
  1141. //
  1142. //  EditStripFirstCharacter()
  1143. //
  1144. void EditStripFirstCharacter(HWND hwnd)
  1145. {
  1146.   int iSelStart = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);
  1147.   int iSelEnd   = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0);
  1148.  
  1149.   if (iSelStart == iSelEnd) {
  1150.     iSelStart = 0;
  1151.     iSelEnd   = SendMessage(hwnd,SCI_GETLENGTH,0,0); }
  1152.  
  1153.   if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  1154.   {
  1155.     int iLine;
  1156.  
  1157.     int iLineStart = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iSelStart,0);
  1158.     int iLineEnd   = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iSelEnd,0);
  1159.  
  1160.     if (iSelStart > SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineStart,0))
  1161.       iLineStart++;
  1162.  
  1163.     if (iSelEnd <= SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineEnd,0))
  1164.       iLineEnd--;
  1165.  
  1166.     SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  1167.  
  1168.     for (iLine = iLineStart; iLine <= iLineEnd; iLine++)
  1169.     {
  1170.       int iPos = SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0);
  1171.       if (SendMessage(hwnd,SCI_GETLINEENDPOSITION,(WPARAM)iLine,0)- iPos > 0)
  1172.       {
  1173.         SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iPos,0);
  1174.         SendMessage(hwnd,SCI_SETTARGETEND,
  1175.           (WPARAM)SendMessage(hwnd,SCI_POSITIONAFTER,(WPARAM)iPos,0),0);
  1176.         SendMessage(hwnd,SCI_REPLACETARGET,0,(LPARAM)"");
  1177.       }
  1178.     }
  1179.     SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  1180.   }
  1181.   else
  1182.     MsgBox(MBINFO,IDS_SELRECT);
  1183. }
  1184.  
  1185.  
  1186. //=============================================================================
  1187. //
  1188. //  EditStripTrailingBlanks()
  1189. //
  1190. void EditStripTrailingBlanks(HWND hwnd)
  1191. {
  1192.   // Check if there is any selection... simply use a regular expression replace!
  1193.   if (SendMessage(hwnd,SCI_GETSELECTIONEND,0,0) - SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0))
  1194.   {
  1195.     if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  1196.     {
  1197.       EDITFINDREPLACE efrTrim = { "[ \t]+$", "", "", "", SCFIND_REGEXP, 0, 0, 0, hwnd };
  1198.       EditReplaceAllInSelection(hwnd,&efrTrim,FALSE);
  1199.     }
  1200.     else
  1201.       MsgBox(MBINFO,IDS_SELRECT);
  1202.   }
  1203.   // Code from SciTE...
  1204.   else
  1205.   {
  1206.     int line;
  1207.     int maxLines;
  1208.     int lineStart;
  1209.     int lineEnd;
  1210.     int i;
  1211.     char ch;
  1212.  
  1213.     SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  1214.     maxLines = SendMessage(hwnd,SCI_GETLINECOUNT,0,0);
  1215.     for (line = 0; line < maxLines; line++)
  1216.     {
  1217.       lineStart = SendMessage(hwnd,SCI_POSITIONFROMLINE,line,0);
  1218.       lineEnd = SendMessage(hwnd,SCI_GETLINEENDPOSITION,line,0);
  1219.       i = lineEnd-1;
  1220.       ch = (char)SendMessage(hwnd,SCI_GETCHARAT,i,0);
  1221.       while ((i >= lineStart) && ((ch == ' ') || (ch == '\t')))
  1222.       {
  1223.         i--;
  1224.         ch = (char)SendMessage(hwnd,SCI_GETCHARAT,i,0);
  1225.       }
  1226.       if (i < (lineEnd-1))
  1227.       {
  1228.         SendMessage(hwnd,SCI_SETTARGETSTART,i + 1,0);
  1229.         SendMessage(hwnd,SCI_SETTARGETEND,lineEnd,0);
  1230.         SendMessage(hwnd,SCI_REPLACETARGET,0,(LPARAM)"");
  1231.       }
  1232.     }
  1233.     SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  1234.   }
  1235. }
  1236.  
  1237.  
  1238. //=============================================================================
  1239. //
  1240. //  EditRemoveBlankLines()
  1241. //
  1242. void EditRemoveBlankLines(HWND hwnd)
  1243. {
  1244.   int iSelStart = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);
  1245.   int iSelEnd   = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0);
  1246.  
  1247.   if (iSelStart == iSelEnd) {
  1248.     iSelStart = 0;
  1249.     iSelEnd   = SendMessage(hwnd,SCI_GETLENGTH,0,0); }
  1250.  
  1251.   if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  1252.   {
  1253.     int iLine;
  1254.  
  1255.     int iLineStart = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iSelStart,0);
  1256.     int iLineEnd   = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iSelEnd,0);
  1257.  
  1258.     if (iSelStart > SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineStart,0))
  1259.       iLineStart++;
  1260.  
  1261.     if (iSelEnd <= SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineEnd,0))
  1262.       iLineEnd--;
  1263.  
  1264.     SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  1265.  
  1266.     for (iLine = iLineStart; iLine <= iLineEnd; )
  1267.     {
  1268.       int iPos = SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine,0);
  1269.       if (SendMessage(hwnd,SCI_GETLINEENDPOSITION,(WPARAM)iLine,0) == iPos)
  1270.       {
  1271.         int iPos2 = SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLine+1,0);
  1272.         SendMessage(hwnd,SCI_SETTARGETSTART,(WPARAM)iPos,0);
  1273.         SendMessage(hwnd,SCI_SETTARGETEND,(WPARAM)iPos2,0);
  1274.         SendMessage(hwnd,SCI_REPLACETARGET,0,(LPARAM)"");
  1275.         iLineEnd--;
  1276.       }
  1277.       else
  1278.         iLine++;
  1279.     }
  1280.     SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  1281.   }
  1282.   else
  1283.     MsgBox(MBINFO,IDS_SELRECT);
  1284. }
  1285.  
  1286.  
  1287. //=============================================================================
  1288. //
  1289. //  EditJumpTo()
  1290. //
  1291. void EditJumpTo(HWND hwnd,int iNewLine,int iNewCol)
  1292. {
  1293.   int iMaxLine = SendMessage(hwnd,SCI_GETLINECOUNT,0,0);
  1294.  
  1295.   // Jumpt to end with line set to -1
  1296.   if (iNewLine == -1) {
  1297.     SendMessage(hwnd,SCI_DOCUMENTEND,0,0);
  1298.     return; }
  1299.  
  1300.   // Line maximum is iMaxLine
  1301.   iNewLine = min(iNewLine,iMaxLine);
  1302.  
  1303.   // Column minimum is 1
  1304.   iNewCol = max(iNewCol,1);
  1305.  
  1306.   if (iNewLine > 0 && iNewLine <= iMaxLine && iNewCol > 0)
  1307.   {
  1308.     int iNewPos  = SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iNewLine-1,0);
  1309.     int iLineEndPos = SendMessage(hwnd,SCI_GETLINEENDPOSITION,(WPARAM)iNewLine-1,0);
  1310.  
  1311.     while (iNewCol-1 > SendMessage(hwnd,SCI_GETCOLUMN,(WPARAM)iNewPos,0))
  1312.     {
  1313.       if (iNewPos >= iLineEndPos)
  1314.         break;
  1315.  
  1316.       iNewPos = SendMessage(hwnd,SCI_POSITIONAFTER,(WPARAM)iNewPos,0);
  1317.     }
  1318.  
  1319.     iNewPos = min(iNewPos,iLineEndPos);
  1320.     SendMessage(hwnd,SCI_GOTOPOS,(WPARAM)iNewPos,0);
  1321.     SendMessage(hwnd,SCI_CHOOSECARETX,0,0);
  1322.   }
  1323. }
  1324.  
  1325.  
  1326. //=============================================================================
  1327. //
  1328. //  EditToggleBookmark()
  1329. //
  1330. void EditToggleBookmark(HWND hwnd)
  1331. {
  1332.   int iCurrentPos = SendMessage(hwnd,SCI_GETCURRENTPOS,0,0);
  1333.   int iCurrentLine = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iCurrentPos,0);
  1334.   int iMarkerBits = SendMessage(hwnd,SCI_MARKERGET,(WPARAM)iCurrentLine,0);
  1335.  
  1336.   if (iMarkerBits & 1) // Bit 0 represents the Notepad2 bookmark
  1337.     SendMessage(hwnd,SCI_MARKERDELETE,(WPARAM)iCurrentLine,0);
  1338.   else
  1339.     SendMessage(hwnd,SCI_MARKERADD,(WPARAM)iCurrentLine,0);
  1340. }
  1341.  
  1342.  
  1343. //=============================================================================
  1344. //
  1345. //  EditJumpToBookmark()
  1346. //
  1347. void EditJumpToBookmark(HWND hwnd,BOOL bNext)
  1348. {
  1349.   int iCurrentPos = SendMessage(hwnd,SCI_GETCURRENTPOS,0,0);
  1350.   int iCurrentLine = SendMessage(hwnd,SCI_LINEFROMPOSITION,(WPARAM)iCurrentPos,0);
  1351.   int iMaxLine = SendMessage(hwnd,SCI_GETLINECOUNT,0,0) - 1;
  1352.  
  1353.   if (bNext)
  1354.   {
  1355.     int iMarkerLine = -1;
  1356.  
  1357.     if (iCurrentLine < iMaxLine)
  1358.       iMarkerLine = SendMessage(hwnd,SCI_MARKERNEXT,(WPARAM)iCurrentLine+1,1);
  1359.  
  1360.     if (iMarkerLine == -1)
  1361.       iMarkerLine = SendMessage(hwnd,SCI_MARKERNEXT,(WPARAM)0,1);
  1362.  
  1363.     if (iMarkerLine != -1) {
  1364.       SendMessage(hwnd,SCI_GOTOLINE,(WPARAM)iMarkerLine,0);
  1365.       SendMessage(hwnd,SCI_CHOOSECARETX,0,0); }
  1366.   }
  1367.  
  1368.   else
  1369.   {
  1370.     int iMarkerLine = -1;
  1371.  
  1372.     if (iCurrentLine > 0)
  1373.       iMarkerLine = SendMessage(hwnd,SCI_MARKERPREVIOUS,(WPARAM)iCurrentLine-1,1);
  1374.  
  1375.     if (iMarkerLine == -1)
  1376.       iMarkerLine = SendMessage(hwnd,SCI_MARKERPREVIOUS,(WPARAM)iMaxLine,1);
  1377.  
  1378.     if (iMarkerLine != -1) {
  1379.       SendMessage(hwnd,SCI_GOTOLINE,(WPARAM)iMarkerLine,0);
  1380.       SendMessage(hwnd,SCI_CHOOSECARETX,0,0); }
  1381.   }
  1382. }
  1383.  
  1384.  
  1385. //=============================================================================
  1386. //
  1387. //  EditClearAllBookmarks()
  1388. //
  1389. void EditClearAllBookmarks(HWND hwnd)
  1390. {
  1391.   SendMessage(hwnd,SCI_MARKERDELETEALL,(WPARAM)-1,0);
  1392. }
  1393.  
  1394.  
  1395. //=============================================================================
  1396. //
  1397. //  EditFindReplaceDlgProcW()
  1398. //
  1399. BOOL CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
  1400. {
  1401.  
  1402.   LPEDITFINDREPLACE lpefr;
  1403.   HANDLE hStrings;
  1404.   int i;
  1405.   char tch[256+32];
  1406.   BOOL bCloseDlg;
  1407.   BOOL bIsFindDlg;
  1408.  
  1409.   CREATEMRULIST mruFind = { sizeof(CREATEMRULIST), 16, 2, HKEY_CURRENT_USER,
  1410.                             "Software\\Notepad2\\Recent Find", NULL };
  1411.   CREATEMRULIST mruReplace = { sizeof(CREATEMRULIST), 16, 2, HKEY_CURRENT_USER,
  1412.                               "Software\\Notepad2\\Recent Replace", NULL };
  1413.  
  1414.   static UINT uCPEdit;
  1415.  
  1416.   switch(umsg)
  1417.   {
  1418.  
  1419.     case WM_INITDIALOG:
  1420.       {
  1421.         int cchSelection;
  1422.         char *lpszSelection;
  1423.         char *lpsz;
  1424.  
  1425.         SetWindowLong(hwnd,DWL_USER,lParam);
  1426.         lpefr = (LPEDITFINDREPLACE)lParam;
  1427.  
  1428.         // Get the current code page for Unicode conversion
  1429.         uCPEdit = SendMessage(lpefr->hwnd,SCI_GETCODEPAGE,0,0);
  1430.  
  1431.         // Load MRUs
  1432.         hStrings = CreateMRUList(&mruFind);
  1433.         for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1434.         {
  1435.           EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1436.           ComboBox_AddStringA2W(CP_UTF8,GetDlgItem(hwnd,IDC_FINDTEXT),tch);
  1437.           //SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1438.         }
  1439.         FreeMRUList(hStrings);
  1440.         hStrings = CreateMRUList(&mruReplace);
  1441.         for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1442.         {
  1443.           EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1444.           ComboBox_AddStringA2W(CP_UTF8,GetDlgItem(hwnd,IDC_REPLACETEXT),tch);
  1445.           //SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1446.         }
  1447.         FreeMRUList(hStrings);
  1448.  
  1449.         cchSelection = SendMessage(lpefr->hwnd,SCI_GETSELECTIONEND,0,0) -
  1450.                        SendMessage(lpefr->hwnd,SCI_GETSELECTIONSTART,0,0);
  1451.  
  1452.         if (cchSelection < 255)
  1453.         {
  1454.           lpszSelection = GlobalAlloc(GPTR,cchSelection+2);
  1455.           SendMessage(lpefr->hwnd,SCI_GETSELTEXT,0,(LPARAM)lpszSelection);
  1456.  
  1457.           // Check lpszSelection and truncate bad chars
  1458.           lpsz = strchr(lpszSelection,13);
  1459.           if (lpsz) *lpsz = '\0';
  1460.  
  1461.           lpsz = strchr(lpszSelection,10);
  1462.           if (lpsz) *lpsz = '\0';
  1463.  
  1464.           lpsz = strchr(lpszSelection,9);
  1465.           if (lpsz) *lpsz = '\0';
  1466.  
  1467.           SetDlgItemTextA2W(uCPEdit,hwnd,IDC_FINDTEXT,lpszSelection);
  1468.           GlobalFree(lpszSelection);
  1469.         }
  1470.  
  1471.         SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_LIMITTEXT,255,0);
  1472.         SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_SETEXTENDEDUI,TRUE,0);
  1473.  
  1474.         if (!GetWindowTextLengthW(GetDlgItem(hwnd,IDC_FINDTEXT)))
  1475.           SetDlgItemTextA2W(CP_UTF8,hwnd,IDC_FINDTEXT,lpefr->szFindUTF8);
  1476.  
  1477.         if (GetDlgItem(hwnd,IDC_REPLACETEXT))
  1478.         {
  1479.           SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_LIMITTEXT,255,0);
  1480.           SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_SETEXTENDEDUI,TRUE,0);
  1481.           SetDlgItemTextA2W(CP_UTF8,hwnd,IDC_REPLACETEXT,lpefr->szReplaceUTF8);
  1482.         }
  1483.  
  1484.         if (lpefr->fuFlags & SCFIND_MATCHCASE)
  1485.           CheckDlgButton(hwnd,IDC_FINDCASE,BST_CHECKED);
  1486.  
  1487.         if (lpefr->fuFlags & SCFIND_WHOLEWORD)
  1488.           CheckDlgButton(hwnd,IDC_FINDWORD,BST_CHECKED);
  1489.  
  1490.         if (lpefr->fuFlags & SCFIND_WORDSTART)
  1491.           CheckDlgButton(hwnd,IDC_FINDSTART,BST_CHECKED);
  1492.  
  1493.         if (lpefr->fuFlags & SCFIND_REGEXP)
  1494.           CheckDlgButton(hwnd,IDC_FINDREGEXP,BST_CHECKED);
  1495.  
  1496.         if (lpefr->bFindUp)
  1497.           CheckDlgButton(hwnd,IDC_FINDUP,BST_CHECKED);
  1498.  
  1499.         if (GetDlgItem(hwnd,IDC_REPLACE)) {
  1500.           if (lpefr->bReplaceClose)
  1501.             CheckDlgButton(hwnd,IDC_FINDCLOSE,BST_CHECKED); }
  1502.         else {
  1503.           if (lpefr->bFindClose)
  1504.             CheckDlgButton(hwnd,IDC_FINDCLOSE,BST_CHECKED); }
  1505.  
  1506.         CenterDlgInParent(hwnd);
  1507.       }
  1508.       return TRUE;
  1509.  
  1510.  
  1511.     case WM_COMMAND:
  1512.  
  1513.       switch(LOWORD(wParam))
  1514.       {
  1515.  
  1516.         case IDC_FINDTEXT:
  1517.         case IDC_REPLACETEXT:
  1518.           {
  1519.             BOOL bEnable = (GetWindowTextLengthW(GetDlgItem(hwnd,IDC_FINDTEXT)) ||
  1520.                             CB_ERR != SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_GETCURSEL,0,0));
  1521.  
  1522.             EnableWindow(GetDlgItem(hwnd,IDOK),bEnable);
  1523.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACE),bEnable);
  1524.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEALL),bEnable);
  1525.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEINSEL),bEnable);
  1526.  
  1527.             if (HIWORD(wParam) == CBN_CLOSEUP) {
  1528.               LONG lSelEnd;
  1529.               SendDlgItemMessage(hwnd,LOWORD(wParam),CB_GETEDITSEL,0,(LPARAM)&lSelEnd);
  1530.               SendDlgItemMessage(hwnd,LOWORD(wParam),CB_SETEDITSEL,0,MAKELPARAM(lSelEnd,lSelEnd)); }
  1531.           }
  1532.           break;
  1533.  
  1534.         case IDOK:
  1535.         case IDC_REPLACE:
  1536.         case IDC_REPLACEALL:
  1537.         case IDC_REPLACEINSEL:
  1538.  
  1539.           (LONG)lpefr = GetWindowLong(hwnd,DWL_USER);
  1540.  
  1541.           if (!GetDlgItemTextA2W(uCPEdit,hwnd,IDC_FINDTEXT,lpefr->szFind,COUNTOF(lpefr->szFind)))
  1542.           {
  1543.             EnableWindow(GetDlgItem(hwnd,IDOK),FALSE);
  1544.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACE),FALSE);
  1545.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEALL),FALSE);
  1546.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEINSEL),FALSE);
  1547.             return TRUE;
  1548.           }
  1549.  
  1550.           if (GetDlgItem(hwnd,IDC_REPLACETEXT))
  1551.             GetDlgItemTextA2W(uCPEdit,hwnd,IDC_REPLACETEXT,lpefr->szReplace,COUNTOF(lpefr->szReplace));
  1552.  
  1553.           lpefr->fuFlags = 0;
  1554.  
  1555.           if (IsDlgButtonChecked(hwnd,IDC_FINDCASE) == BST_CHECKED)
  1556.             lpefr->fuFlags |= SCFIND_MATCHCASE;
  1557.  
  1558.           if (IsDlgButtonChecked(hwnd,IDC_FINDWORD) == BST_CHECKED)
  1559.             lpefr->fuFlags |= SCFIND_WHOLEWORD;
  1560.  
  1561.           if (IsDlgButtonChecked(hwnd,IDC_FINDSTART) == BST_CHECKED)
  1562.             lpefr->fuFlags |= SCFIND_WORDSTART;
  1563.  
  1564.           if (IsDlgButtonChecked(hwnd,IDC_FINDREGEXP) == BST_CHECKED)
  1565.             lpefr->fuFlags |= SCFIND_REGEXP;
  1566.  
  1567.           lpefr->bFindUp = (IsDlgButtonChecked(hwnd,IDC_FINDUP) == BST_CHECKED) ? TRUE : FALSE;
  1568.  
  1569.           bIsFindDlg = (GetDlgItem(hwnd,IDC_REPLACE) == NULL);
  1570.           if (bIsFindDlg) {
  1571.             lpefr->bFindClose = (IsDlgButtonChecked(hwnd,IDC_FINDCLOSE) == BST_CHECKED) ? TRUE : FALSE; }
  1572.           else {
  1573.             lpefr->bReplaceClose = (IsDlgButtonChecked(hwnd,IDC_FINDCLOSE) == BST_CHECKED) ? TRUE : FALSE; }
  1574.  
  1575.           // Save MRUs
  1576.           if (lstrlen(lpefr->szFind))
  1577.           {
  1578.             if (GetDlgItemTextA2W(CP_UTF8,hwnd,IDC_FINDTEXT,lpefr->szFindUTF8,COUNTOF(lpefr->szFindUTF8))) {
  1579.               hStrings = CreateMRUList(&mruFind);
  1580.               AddMRUString(hStrings,lpefr->szFindUTF8);
  1581.               FreeMRUList(hStrings); }
  1582.           }
  1583.           if (lstrlen(lpefr->szReplace))
  1584.           {
  1585.             if (GetDlgItemTextA2W(CP_UTF8,hwnd,IDC_REPLACETEXT,lpefr->szReplaceUTF8,COUNTOF(lpefr->szReplaceUTF8))) {
  1586.               hStrings = CreateMRUList(&mruReplace);
  1587.               AddMRUString(hStrings,lpefr->szReplaceUTF8);
  1588.               FreeMRUList(hStrings); }
  1589.           }
  1590.  
  1591.           if (bIsFindDlg) {
  1592.             bCloseDlg = lpefr->bFindClose; }
  1593.           else {
  1594.             if (LOWORD(wParam) == IDOK)
  1595.               bCloseDlg = FALSE;
  1596.             else
  1597.               bCloseDlg = lpefr->bReplaceClose; }
  1598.  
  1599.           if (bCloseDlg)
  1600.             EndDialog(hwnd,LOWORD(wParam));
  1601.  
  1602.           else {
  1603.  
  1604.             // Reload MRUs
  1605.             SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_RESETCONTENT,0,0);
  1606.             SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_RESETCONTENT,0,0);
  1607.  
  1608.             hStrings = CreateMRUList(&mruFind);
  1609.             for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1610.             {
  1611.               EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1612.               ComboBox_AddStringA2W(CP_UTF8,GetDlgItem(hwnd,IDC_FINDTEXT),tch);
  1613.               //SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1614.             }
  1615.             FreeMRUList(hStrings);
  1616.             hStrings = CreateMRUList(&mruReplace);
  1617.             for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1618.             {
  1619.               EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1620.               ComboBox_AddStringA2W(CP_UTF8,GetDlgItem(hwnd,IDC_REPLACETEXT),tch);
  1621.               //SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1622.             }
  1623.             FreeMRUList(hStrings);
  1624.  
  1625.             SetDlgItemTextA2W(CP_UTF8,hwnd,IDC_FINDTEXT,lpefr->szFindUTF8);
  1626.             SetDlgItemTextA2W(CP_UTF8,hwnd,IDC_REPLACETEXT,lpefr->szReplaceUTF8);
  1627.  
  1628.             SendMessage(hwnd,WM_NEXTDLGCTL,(WPARAM)(GetFocus()),1);
  1629.  
  1630.             switch (LOWORD(wParam))
  1631.             {
  1632.               case IDOK: // find
  1633.                 if (!lpefr->bFindUp)
  1634.                   EditFindNext(lpefr->hwnd,lpefr);
  1635.                 else
  1636.                   EditFindPrev(lpefr->hwnd,lpefr);
  1637.                 break;
  1638.  
  1639.               case IDC_REPLACE:
  1640.                 EditReplace(lpefr->hwnd,lpefr);
  1641.                 break;
  1642.  
  1643.               case IDC_REPLACEALL:
  1644.                 EditReplaceAll(lpefr->hwnd,lpefr,TRUE);
  1645.                 break;
  1646.  
  1647.               case IDC_REPLACEINSEL:
  1648.                 EditReplaceAllInSelection(lpefr->hwnd,lpefr,TRUE);
  1649.                 break;
  1650.             }
  1651.           }
  1652.           break;
  1653.  
  1654.  
  1655.         case IDCANCEL:
  1656.  
  1657.           EndDialog(hwnd,IDCANCEL);
  1658.           break;
  1659.  
  1660.       }
  1661.  
  1662.       return TRUE;
  1663.  
  1664.   }
  1665.  
  1666.   return FALSE;
  1667.  
  1668. }
  1669.  
  1670.  
  1671. //=============================================================================
  1672. //
  1673. //  EditFindReplaceDlgProcA()
  1674. //
  1675. BOOL CALLBACK EditFindReplaceDlgProcA(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
  1676. {
  1677.  
  1678.   LPEDITFINDREPLACE lpefr;
  1679.   HANDLE hStrings;
  1680.   int i;
  1681.   char tch[256+32];
  1682.   BOOL bCloseDlg;
  1683.   BOOL bIsFindDlg;
  1684.  
  1685.   CREATEMRULIST mruFind = { sizeof(CREATEMRULIST), 16, 2, HKEY_CURRENT_USER,
  1686.                             "Software\\Notepad2\\Recent Find", NULL };
  1687.   CREATEMRULIST mruReplace = { sizeof(CREATEMRULIST), 16, 2, HKEY_CURRENT_USER,
  1688.                               "Software\\Notepad2\\Recent Replace", NULL };
  1689.  
  1690.   switch(umsg)
  1691.   {
  1692.  
  1693.     case WM_INITDIALOG:
  1694.       {
  1695.         int cchSelection;
  1696.         char *lpszSelection;
  1697.         char *lpsz;
  1698.  
  1699.         SetWindowLong(hwnd,DWL_USER,lParam);
  1700.         lpefr = (LPEDITFINDREPLACE)lParam;
  1701.  
  1702.         // Load MRUs
  1703.         hStrings = CreateMRUList(&mruFind);
  1704.         for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1705.         {
  1706.           EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1707.           SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1708.         }
  1709.         FreeMRUList(hStrings);
  1710.         hStrings = CreateMRUList(&mruReplace);
  1711.         for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1712.         {
  1713.           EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1714.           SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1715.         }
  1716.         FreeMRUList(hStrings);
  1717.  
  1718.         cchSelection = SendMessage(lpefr->hwnd,SCI_GETSELECTIONEND,0,0) -
  1719.                        SendMessage(lpefr->hwnd,SCI_GETSELECTIONSTART,0,0);
  1720.  
  1721.         if (cchSelection < 255)
  1722.         {
  1723.           lpszSelection = GlobalAlloc(GPTR,cchSelection+2);
  1724.           SendMessage(lpefr->hwnd,SCI_GETSELTEXT,0,(LPARAM)lpszSelection);
  1725.  
  1726.           // Check lpszSelection and truncate bad chars
  1727.           lpsz = strchr(lpszSelection,13);
  1728.           if (lpsz) *lpsz = '\0';
  1729.  
  1730.           lpsz = strchr(lpszSelection,10);
  1731.           if (lpsz) *lpsz = '\0';
  1732.  
  1733.           lpsz = strchr(lpszSelection,9);
  1734.           if (lpsz) *lpsz = '\0';
  1735.  
  1736.           SetDlgItemText(hwnd,IDC_FINDTEXT,lpszSelection);
  1737.           GlobalFree(lpszSelection);
  1738.         }
  1739.  
  1740.         SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_LIMITTEXT,255,0);
  1741.         SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_SETEXTENDEDUI,TRUE,0);
  1742.  
  1743.         if (!GetWindowTextLength(GetDlgItem(hwnd,IDC_FINDTEXT)))
  1744.           SetDlgItemText(hwnd,IDC_FINDTEXT,lpefr->szFind);
  1745.  
  1746.         if (GetDlgItem(hwnd,IDC_REPLACETEXT))
  1747.         {
  1748.           SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_LIMITTEXT,255,0);
  1749.           SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_SETEXTENDEDUI,TRUE,0);
  1750.           SetDlgItemText(hwnd,IDC_REPLACETEXT,lpefr->szReplace);
  1751.         }
  1752.  
  1753.         if (lpefr->fuFlags & SCFIND_MATCHCASE)
  1754.           CheckDlgButton(hwnd,IDC_FINDCASE,BST_CHECKED);
  1755.  
  1756.         if (lpefr->fuFlags & SCFIND_WHOLEWORD)
  1757.           CheckDlgButton(hwnd,IDC_FINDWORD,BST_CHECKED);
  1758.  
  1759.         if (lpefr->fuFlags & SCFIND_WORDSTART)
  1760.           CheckDlgButton(hwnd,IDC_FINDSTART,BST_CHECKED);
  1761.  
  1762.         if (lpefr->fuFlags & SCFIND_REGEXP)
  1763.           CheckDlgButton(hwnd,IDC_FINDREGEXP,BST_CHECKED);
  1764.  
  1765.         if (lpefr->bFindUp)
  1766.           CheckDlgButton(hwnd,IDC_FINDUP,BST_CHECKED);
  1767.  
  1768.         if (GetDlgItem(hwnd,IDC_REPLACE)) {
  1769.           if (lpefr->bReplaceClose)
  1770.             CheckDlgButton(hwnd,IDC_FINDCLOSE,BST_CHECKED); }
  1771.         else {
  1772.           if (lpefr->bFindClose)
  1773.             CheckDlgButton(hwnd,IDC_FINDCLOSE,BST_CHECKED); }
  1774.  
  1775.         CenterDlgInParent(hwnd);
  1776.       }
  1777.       return TRUE;
  1778.  
  1779.  
  1780.     case WM_COMMAND:
  1781.  
  1782.       switch(LOWORD(wParam))
  1783.       {
  1784.  
  1785.         case IDC_FINDTEXT:
  1786.         case IDC_REPLACETEXT:
  1787.           {
  1788.             BOOL bEnable = (GetWindowTextLength(GetDlgItem(hwnd,IDC_FINDTEXT)) ||
  1789.                             CB_ERR != SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_GETCURSEL,0,0));
  1790.  
  1791.             EnableWindow(GetDlgItem(hwnd,IDOK),bEnable);
  1792.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACE),bEnable);
  1793.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEALL),bEnable);
  1794.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEINSEL),bEnable);
  1795.  
  1796.             if (HIWORD(wParam) == CBN_CLOSEUP) {
  1797.               LONG lSelEnd;
  1798.               SendDlgItemMessage(hwnd,LOWORD(wParam),CB_GETEDITSEL,0,(LPARAM)&lSelEnd);
  1799.               SendDlgItemMessage(hwnd,LOWORD(wParam),CB_SETEDITSEL,0,MAKELPARAM(lSelEnd,lSelEnd)); }
  1800.           }
  1801.           break;
  1802.  
  1803.         case IDOK:
  1804.         case IDC_REPLACE:
  1805.         case IDC_REPLACEALL:
  1806.         case IDC_REPLACEINSEL:
  1807.  
  1808.           (LONG)lpefr = GetWindowLong(hwnd,DWL_USER);
  1809.  
  1810.           if (!GetDlgItemText(hwnd,IDC_FINDTEXT,lpefr->szFind,COUNTOF(lpefr->szFind)))
  1811.           {
  1812.             EnableWindow(GetDlgItem(hwnd,IDOK),FALSE);
  1813.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACE),FALSE);
  1814.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEALL),FALSE);
  1815.             EnableWindow(GetDlgItem(hwnd,IDC_REPLACEINSEL),FALSE);
  1816.             return TRUE;
  1817.           }
  1818.  
  1819.           if (GetDlgItem(hwnd,IDC_REPLACETEXT))
  1820.             GetDlgItemText(hwnd,IDC_REPLACETEXT,lpefr->szReplace,COUNTOF(lpefr->szReplace));
  1821.  
  1822.           lpefr->fuFlags = 0;
  1823.  
  1824.           if (IsDlgButtonChecked(hwnd,IDC_FINDCASE) == BST_CHECKED)
  1825.             lpefr->fuFlags |= SCFIND_MATCHCASE;
  1826.  
  1827.           if (IsDlgButtonChecked(hwnd,IDC_FINDWORD) == BST_CHECKED)
  1828.             lpefr->fuFlags |= SCFIND_WHOLEWORD;
  1829.  
  1830.           if (IsDlgButtonChecked(hwnd,IDC_FINDSTART) == BST_CHECKED)
  1831.             lpefr->fuFlags |= SCFIND_WORDSTART;
  1832.  
  1833.           if (IsDlgButtonChecked(hwnd,IDC_FINDREGEXP) == BST_CHECKED)
  1834.             lpefr->fuFlags |= SCFIND_REGEXP;
  1835.  
  1836.           lpefr->bFindUp = (IsDlgButtonChecked(hwnd,IDC_FINDUP) == BST_CHECKED) ? TRUE : FALSE;
  1837.  
  1838.           bIsFindDlg = (GetDlgItem(hwnd,IDC_REPLACE) == NULL);
  1839.           if (bIsFindDlg) {
  1840.             lpefr->bFindClose = (IsDlgButtonChecked(hwnd,IDC_FINDCLOSE) == BST_CHECKED) ? TRUE : FALSE; }
  1841.           else {
  1842.             lpefr->bReplaceClose = (IsDlgButtonChecked(hwnd,IDC_FINDCLOSE) == BST_CHECKED) ? TRUE : FALSE; }
  1843.  
  1844.           // Save MRUs
  1845.           if (lstrlen(lpefr->szFind))
  1846.           {
  1847.             hStrings = CreateMRUList(&mruFind);
  1848.             AddMRUString(hStrings,lpefr->szFind);
  1849.             FreeMRUList(hStrings);
  1850.           }
  1851.           if (lstrlen(lpefr->szReplace))
  1852.           {
  1853.             hStrings = CreateMRUList(&mruReplace);
  1854.             AddMRUString(hStrings,lpefr->szReplace);
  1855.             FreeMRUList(hStrings);
  1856.           }
  1857.  
  1858.           if (bIsFindDlg) {
  1859.             bCloseDlg = lpefr->bFindClose; }
  1860.           else {
  1861.             if (LOWORD(wParam) == IDOK)
  1862.               bCloseDlg = FALSE;
  1863.             else
  1864.               bCloseDlg = lpefr->bReplaceClose; }
  1865.  
  1866.           if (bCloseDlg)
  1867.             EndDialog(hwnd,LOWORD(wParam));
  1868.  
  1869.           else {
  1870.  
  1871.             // Reload MRUs
  1872.             SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_RESETCONTENT,0,0);
  1873.             SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_RESETCONTENT,0,0);
  1874.  
  1875.             hStrings = CreateMRUList(&mruFind);
  1876.             for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1877.             {
  1878.               EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1879.               SendDlgItemMessage(hwnd,IDC_FINDTEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1880.             }
  1881.             FreeMRUList(hStrings);
  1882.             hStrings = CreateMRUList(&mruReplace);
  1883.             for (i = 0; i < EnumMRUList(hStrings,0,NULL,0); i++)
  1884.             {
  1885.               EnumMRUList(hStrings,i,tch,COUNTOF(tch));
  1886.               SendDlgItemMessage(hwnd,IDC_REPLACETEXT,CB_ADDSTRING,0,(LPARAM)tch);
  1887.             }
  1888.             FreeMRUList(hStrings);
  1889.  
  1890.             SetDlgItemText(hwnd,IDC_FINDTEXT,lpefr->szFind);
  1891.             SetDlgItemText(hwnd,IDC_REPLACETEXT,lpefr->szReplace);
  1892.  
  1893.             SendMessage(hwnd,WM_NEXTDLGCTL,(WPARAM)(GetFocus()),1);
  1894.  
  1895.             switch (LOWORD(wParam))
  1896.             {
  1897.               case IDOK: // find
  1898.                 if (!lpefr->bFindUp)
  1899.                   EditFindNext(lpefr->hwnd,lpefr);
  1900.                 else
  1901.                   EditFindPrev(lpefr->hwnd,lpefr);
  1902.                 break;
  1903.  
  1904.               case IDC_REPLACE:
  1905.                 EditReplace(lpefr->hwnd,lpefr);
  1906.                 break;
  1907.  
  1908.               case IDC_REPLACEALL:
  1909.                 EditReplaceAll(lpefr->hwnd,lpefr,TRUE);
  1910.                 break;
  1911.  
  1912.               case IDC_REPLACEINSEL:
  1913.                 EditReplaceAllInSelection(lpefr->hwnd,lpefr,TRUE);
  1914.                 break;
  1915.             }
  1916.           }
  1917.           break;
  1918.  
  1919.  
  1920.         case IDCANCEL:
  1921.  
  1922.           EndDialog(hwnd,IDCANCEL);
  1923.           break;
  1924.  
  1925.       }
  1926.  
  1927.       return TRUE;
  1928.  
  1929.   }
  1930.  
  1931.   return FALSE;
  1932.  
  1933. }
  1934.  
  1935.  
  1936. //=============================================================================
  1937. //
  1938. //  EditFindReplaceDlg()
  1939. //
  1940. BOOL EditFindReplaceDlg(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bReplace)
  1941. {
  1942.  
  1943.   int iResult;
  1944.  
  1945.   lpefr->hwnd = hwnd;
  1946.  
  1947.   if (IsWindowsNT()) {
  1948.     iResult = DialogBoxParamW(
  1949.                 g_hInstance,
  1950.                 (bReplace) ? MAKEINTRESOURCEW(IDD_REPLACE) : MAKEINTRESOURCEW(IDD_FIND),
  1951.                 GetParent(hwnd),
  1952.                 EditFindReplaceDlgProcW,
  1953.                 (LPARAM) lpefr); }
  1954.  
  1955.   else {
  1956.     iResult = DialogBoxParamA(
  1957.                 g_hInstance,
  1958.                 (bReplace) ? MAKEINTRESOURCE(IDD_REPLACE) : MAKEINTRESOURCE(IDD_FIND),
  1959.                 GetParent(hwnd),
  1960.                 EditFindReplaceDlgProcA,
  1961.                 (LPARAM) lpefr); }
  1962.  
  1963.   if (iResult == IDOK) { // IDOK always means "find"
  1964.     if (!lpefr->bFindUp)
  1965.       return EditFindNext(hwnd,lpefr);
  1966.     else
  1967.       return EditFindPrev(hwnd,lpefr); }
  1968.  
  1969.   if (iResult == IDC_REPLACE)
  1970.     return EditReplace(hwnd,lpefr);
  1971.  
  1972.   if (iResult == IDC_REPLACEALL)
  1973.     return EditReplaceAll(hwnd,lpefr,TRUE);
  1974.  
  1975.   if (iResult == IDC_REPLACEINSEL)
  1976.     return EditReplaceAllInSelection(hwnd,lpefr,TRUE);
  1977.  
  1978.   return FALSE;
  1979.  
  1980. }
  1981.  
  1982.  
  1983. //=============================================================================
  1984. //
  1985. //  EditFindNext()
  1986. //
  1987. BOOL EditFindNext(HWND hwnd,LPCEDITFINDREPLACE lpefr)
  1988. {
  1989.  
  1990.   struct TextToFind ttf;
  1991.   int iPos;
  1992.  
  1993.   if (!lstrlen(lpefr->szFind))
  1994.     return EditFindReplaceDlg(hwnd,lpefr,FALSE);
  1995.  
  1996.   ZeroMemory(&ttf,sizeof(ttf));
  1997.  
  1998.   ttf.chrg.cpMin = SendMessage(hwnd,SCI_GETSELECTIONEND,0,0);
  1999.   ttf.chrg.cpMax = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2000.   ttf.lpstrText = lpefr->szFind;
  2001.  
  2002.   iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf);
  2003.  
  2004.   if (iPos == -1 && ttf.chrg.cpMin > 0)
  2005.   {
  2006.     // wrapped
  2007.     MsgBox(MBINFO,IDS_FIND_WRAPFW);
  2008.  
  2009.     ttf.chrg.cpMin = 0;
  2010.     iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf);
  2011.   }
  2012.  
  2013.   if (iPos == -1)
  2014.   {
  2015.     // notfound
  2016.     MsgBox(MBINFO,IDS_NOTFOUND);
  2017.     return FALSE;
  2018.   }
  2019.  
  2020.   SendMessage(hwnd,SCI_SETSEL,ttf.chrgText.cpMin,ttf.chrgText.cpMax);
  2021.  
  2022.   return TRUE;
  2023.  
  2024. }
  2025.  
  2026.  
  2027. //=============================================================================
  2028. //
  2029. //  EditFindPrev()
  2030. //
  2031. BOOL EditFindPrev(HWND hwnd,LPCEDITFINDREPLACE lpefr)
  2032. {
  2033.  
  2034.   struct TextToFind ttf;
  2035.   int iPos;
  2036.   int iLength;
  2037.  
  2038.   if (!lstrlen(lpefr->szFind))
  2039.     return EditFindReplaceDlg(hwnd,lpefr,FALSE);
  2040.  
  2041.   ZeroMemory(&ttf,sizeof(ttf));
  2042.  
  2043.   ttf.chrg.cpMin = max(0,SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0)-1);
  2044.   ttf.chrg.cpMax = 0;
  2045.   ttf.lpstrText = lpefr->szFind;
  2046.  
  2047.   iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf);
  2048.  
  2049.   iLength = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2050.   if (iPos == -1 && ttf.chrg.cpMin < iLength)
  2051.   {
  2052.     // wrapped
  2053.     MsgBox(MBINFO,IDS_FIND_WRAPRE);
  2054.  
  2055.     ttf.chrg.cpMin = iLength;
  2056.     iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf);
  2057.   }
  2058.  
  2059.   if (iPos == -1)
  2060.   {
  2061.     // notfound
  2062.     MsgBox(MBINFO,IDS_NOTFOUND);
  2063.     return FALSE;
  2064.   }
  2065.  
  2066.   SendMessage(hwnd,SCI_SETSEL,ttf.chrgText.cpMin,ttf.chrgText.cpMax);
  2067.  
  2068.   return TRUE;
  2069.  
  2070. }
  2071.  
  2072.  
  2073. //=============================================================================
  2074. //
  2075. //  EditReplace()
  2076. //
  2077. BOOL EditReplace(HWND hwnd,LPCEDITFINDREPLACE lpefr)
  2078. {
  2079.  
  2080.   struct TextToFind ttf;
  2081.   int iPos;
  2082.   int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET;
  2083.  
  2084.   if (!lstrlen(lpefr->szFind))
  2085.     return EditFindReplaceDlg(hwnd,lpefr,TRUE);
  2086.  
  2087.   ZeroMemory(&ttf,sizeof(ttf));
  2088.  
  2089.   ttf.chrg.cpMin = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0); // Start!
  2090.   ttf.chrg.cpMax = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2091.   ttf.lpstrText = lpefr->szFind;
  2092.  
  2093.   iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf);
  2094.  
  2095.   if (iPos == -1 && ttf.chrg.cpMin > 0)
  2096.   {
  2097.     // wrapped
  2098.     MsgBox(MBINFO,IDS_FIND_WRAPFW);
  2099.  
  2100.     ttf.chrg.cpMin = 0;
  2101.     iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf);
  2102.   }
  2103.  
  2104.   if (iPos == -1)
  2105.   {
  2106.     // notfound
  2107.     MsgBox(MBINFO,IDS_NOTFOUND);
  2108.     return FALSE;
  2109.   }
  2110.  
  2111.   //SendMessage(hwnd,SCI_SETSEL,ttf.chrgText.cpMin,ttf.chrgText.cpMax);
  2112.   SendMessage(hwnd,SCI_SETTARGETSTART,ttf.chrgText.cpMin,0);
  2113.   SendMessage(hwnd,SCI_SETTARGETEND,ttf.chrgText.cpMax,0);
  2114.   SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)lpefr->szReplace);
  2115.  
  2116.   SendMessage(hwnd,SCI_SETSEL,SendMessage(hwnd,SCI_GETTARGETSTART,0,0),SendMessage(hwnd,SCI_GETTARGETEND,0,0));
  2117.  
  2118.   return TRUE;
  2119.  
  2120. }
  2121.  
  2122.  
  2123. //=============================================================================
  2124. //
  2125. //  EditReplaceAll()
  2126. //
  2127. BOOL EditReplaceAll(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo)
  2128. {
  2129.  
  2130.   struct TextToFind ttf;
  2131.   int iPos;
  2132.   int iCount = 0;
  2133.   int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET;
  2134.   int iReplaceLen = lstrlen(lpefr->szReplace);
  2135.  
  2136.   if (!lstrlen(lpefr->szFind))
  2137.     return EditFindReplaceDlg(hwnd,lpefr,TRUE);
  2138.  
  2139.   // Show wait cursor...
  2140.   SendMessage(hwnd,SCI_SETCURSOR,SC_CURSORWAIT,0);
  2141.  
  2142.   ZeroMemory(&ttf,sizeof(ttf));
  2143.  
  2144.   ttf.chrg.cpMin = 0;
  2145.   ttf.chrg.cpMax = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2146.   ttf.lpstrText = lpefr->szFind;
  2147.  
  2148.   while ((iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf)) != -1)
  2149.   {
  2150.     iCount++;
  2151.  
  2152.     if (iCount == 1)
  2153.       SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  2154.  
  2155.     SendMessage(hwnd,SCI_SETTARGETSTART,ttf.chrgText.cpMin,0);
  2156.     SendMessage(hwnd,SCI_SETTARGETEND,ttf.chrgText.cpMax,0);
  2157.     SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)lpefr->szReplace);
  2158.  
  2159.     ttf.chrg.cpMin = SendMessage(hwnd,SCI_GETTARGETEND,0,0);
  2160.     ttf.chrg.cpMax = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2161.  
  2162.     if (ttf.chrg.cpMin == ttf.chrg.cpMax ||
  2163.         (ttf.chrgText.cpMin == ttf.chrgText.cpMax && iReplaceLen == 0)) // check for empty target and empty replace
  2164.       break;
  2165.   }
  2166.  
  2167.   if (iCount)
  2168.     SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  2169.  
  2170.   // Remove wait cursor
  2171.   SendMessage(hwnd,SCI_SETCURSOR,SC_CURSORNORMAL,0);
  2172.  
  2173.   if (bShowInfo)
  2174.     MsgBox(MBINFO,IDS_REPLCOUNT,iCount);
  2175.  
  2176.   return TRUE;
  2177.  
  2178. }
  2179.  
  2180.  
  2181. //=============================================================================
  2182. //
  2183. //  EditReplaceAllInSelection()
  2184. //
  2185. BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo)
  2186. {
  2187.  
  2188.   struct TextToFind ttf;
  2189.   int iPos;
  2190.   int iCount = 0;
  2191.   int iReplaceMsg = (lpefr->fuFlags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET;
  2192.   int iReplaceLen = lstrlen(lpefr->szReplace);
  2193.   BOOL fCancel = FALSE;
  2194.  
  2195.   if (SC_SEL_RECTANGLE == SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0))
  2196.   {
  2197.     MsgBox(MBINFO,IDS_SELRECT);
  2198.     return FALSE;
  2199.   }
  2200.  
  2201.   if (!lstrlen(lpefr->szFind))
  2202.     return EditFindReplaceDlg(hwnd,lpefr,TRUE);
  2203.  
  2204.   // Show wait cursor...
  2205.   SendMessage(hwnd,SCI_SETCURSOR,SC_CURSORWAIT,0);
  2206.  
  2207.   ZeroMemory(&ttf,sizeof(ttf));
  2208.  
  2209.   ttf.chrg.cpMin = SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0);
  2210.   ttf.chrg.cpMax = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2211.   ttf.lpstrText = lpefr->szFind;
  2212.  
  2213.   while ((iPos = SendMessage(hwnd,SCI_FINDTEXT,lpefr->fuFlags,(LPARAM)&ttf)) != -1 && !fCancel)
  2214.   {
  2215.     if (ttf.chrgText.cpMin >= SendMessage(hwnd,SCI_GETSELECTIONSTART,0,0) &&
  2216.         ttf.chrgText.cpMax <= SendMessage(hwnd,SCI_GETSELECTIONEND,0,0))
  2217.     {
  2218.       iCount++;
  2219.  
  2220.       if (iCount == 1)
  2221.         SendMessage(hwnd,SCI_BEGINUNDOACTION,0,0);
  2222.  
  2223.       SendMessage(hwnd,SCI_SETTARGETSTART,ttf.chrgText.cpMin,0);
  2224.       SendMessage(hwnd,SCI_SETTARGETEND,ttf.chrgText.cpMax,0);
  2225.       SendMessage(hwnd,iReplaceMsg,(WPARAM)-1,(LPARAM)lpefr->szReplace);
  2226.  
  2227.       ttf.chrg.cpMin = SendMessage(hwnd,SCI_GETTARGETEND,0,0);
  2228.       ttf.chrg.cpMax = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2229.     }
  2230.  
  2231.     else
  2232.     {
  2233.       //ttf.chrg.cpMin = ttf.chrgText.cpMax;
  2234.       //ttf.chrg.cpMax = SendMessage(hwnd,SCI_GETLENGTH,0,0);
  2235.  
  2236.       // gone across selection, cancel
  2237.       fCancel = TRUE;
  2238.     }
  2239.  
  2240.     if (ttf.chrg.cpMin == ttf.chrg.cpMax ||
  2241.         (ttf.chrgText.cpMin == ttf.chrgText.cpMax && iReplaceLen == 0)) // check for empty target and empty replace
  2242.       break;
  2243.   }
  2244.  
  2245.   if (iCount)
  2246.     SendMessage(hwnd,SCI_ENDUNDOACTION,0,0);
  2247.  
  2248.   // Remove wait cursor
  2249.   SendMessage(hwnd,SCI_SETCURSOR,SC_CURSORNORMAL,0);
  2250.  
  2251.   if (bShowInfo)
  2252.     MsgBox(MBINFO,IDS_REPLCOUNT,iCount);
  2253.  
  2254.   return TRUE;
  2255.  
  2256. }
  2257.  
  2258.  
  2259. //=============================================================================
  2260. //
  2261. //  EditLinenumDlgProc()
  2262. //
  2263. BOOL CALLBACK EditLinenumDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
  2264. {
  2265.  
  2266.   switch(umsg)
  2267.   {
  2268.  
  2269.     case WM_INITDIALOG:
  2270.       {
  2271.  
  2272.         int iCurLine = SendMessage(hwndEdit,SCI_LINEFROMPOSITION,
  2273.                          SendMessage(hwndEdit,SCI_GETCURRENTPOS,0,0),0)+1;
  2274.  
  2275.         SetDlgItemInt(hwnd,IDC_LINENUM,iCurLine,FALSE);
  2276.         SendDlgItemMessage(hwnd,IDC_LINENUM,EM_LIMITTEXT,15,0);
  2277.  
  2278.         SendDlgItemMessage(hwnd,IDC_COLNUM,EM_LIMITTEXT,15,0);
  2279.  
  2280.         CenterDlgInParent(hwnd);
  2281.  
  2282.       }
  2283.       return TRUE;
  2284.  
  2285.  
  2286.     case WM_COMMAND:
  2287.  
  2288.       switch(LOWORD(wParam))
  2289.       {
  2290.  
  2291.         case IDOK: {
  2292.  
  2293.           BOOL fTranslated;
  2294.           BOOL fTranslated2;
  2295.  
  2296.           int iNewCol;
  2297.  
  2298.           int iNewLine = GetDlgItemInt(hwnd,IDC_LINENUM,&fTranslated,FALSE);
  2299.           int iMaxLine = SendMessage(hwndEdit,SCI_GETLINECOUNT,0,0);
  2300.  
  2301.           if (SendDlgItemMessage(hwnd,IDC_COLNUM,WM_GETTEXTLENGTH,0,0) > 0)
  2302.             iNewCol = GetDlgItemInt(hwnd,IDC_COLNUM,&fTranslated2,FALSE);
  2303.           else {
  2304.             iNewCol = 1;
  2305.             fTranslated2 = TRUE; }
  2306.  
  2307.           if (!fTranslated || !fTranslated2)
  2308.           {
  2309.             PostMessage(hwnd,WM_NEXTDLGCTL,(WPARAM)(GetDlgItem(hwnd,(!fTranslated) ? IDC_LINENUM : IDC_COLNUM)),1);
  2310.             return TRUE;
  2311.           }
  2312.  
  2313.           if (iNewLine > 0 && iNewLine <= iMaxLine && iNewCol > 0)
  2314.           {
  2315.             //int iNewPos  = SendMessage(hwndEdit,SCI_POSITIONFROMLINE,(WPARAM)iNewLine-1,0);
  2316.             //int iLineEndPos = SendMessage(hwndEdit,SCI_GETLINEENDPOSITION,(WPARAM)iNewLine-1,0);
  2317.  
  2318.             //while (iNewCol-1 > SendMessage(hwndEdit,SCI_GETCOLUMN,(WPARAM)iNewPos,0))
  2319.             //{
  2320.             //  if (iNewPos >= iLineEndPos)
  2321.             //    break;
  2322.  
  2323.             //  iNewPos = SendMessage(hwndEdit,SCI_POSITIONAFTER,(WPARAM)iNewPos,0);
  2324.             //}
  2325.  
  2326.             //iNewPos = min(iNewPos,iLineEndPos);
  2327.             //SendMessage(hwndEdit,SCI_GOTOPOS,(WPARAM)iNewPos,0);
  2328.             //SendMessage(hwndEdit,SCI_CHOOSECARETX,0,0);
  2329.  
  2330.             EditJumpTo(hwndEdit,iNewLine,iNewCol);
  2331.  
  2332.             EndDialog(hwnd,IDOK);
  2333.           }
  2334.  
  2335.           else
  2336.             PostMessage(hwnd,WM_NEXTDLGCTL,(WPARAM)(GetDlgItem(hwnd,(!(iNewLine > 0 && iNewLine <= iMaxLine)) ? IDC_LINENUM : IDC_COLNUM)),1);
  2337.  
  2338.           }
  2339.           break;
  2340.  
  2341.  
  2342.         case IDCANCEL:
  2343.           EndDialog(hwnd,IDCANCEL);
  2344.           break;
  2345.  
  2346.       }
  2347.  
  2348.       return TRUE;
  2349.  
  2350.   }
  2351.  
  2352.   return FALSE;
  2353.  
  2354. }
  2355.  
  2356.  
  2357. //=============================================================================
  2358. //
  2359. //  EditLinenumDlg()
  2360. //
  2361. BOOL EditLinenumDlg(HWND hwnd)
  2362. {
  2363.  
  2364.   if (IDOK == DialogBoxParam(g_hInstance,MAKEINTRESOURCE(IDD_LINENUM),
  2365.                              GetParent(hwnd),EditLinenumDlgProc,(LPARAM)hwnd))
  2366.     return TRUE;
  2367.  
  2368.   else
  2369.     return FALSE;
  2370.  
  2371. }
  2372.  
  2373.  
  2374.  
  2375. ///   End of Edit.c   \\\
  2376.