home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / edprops.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  251.4 KB  |  7,779 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. // edprops.cpp : implementation file
  20. //
  21. #include "stdafx.h"
  22. #ifdef EDITOR
  23. #include "edres2.h"
  24. #include "property.h"
  25. #include "edprops.h"
  26. #include "edttypes.h"
  27. #include "edt.h"
  28. #include "pa_tags.h"
  29. #include "netsvw.h"
  30. #include "edview.h"
  31. #include "styles.h" // For WFE_DrawSwatch()
  32. #ifndef XP_WIN32
  33. #include "tooltip.h"
  34. #endif
  35. #include "nethelp.h"
  36. #include "xp_help.h"
  37. #include "prefapi.h"
  38. #include "prefinfo.h"
  39. // the dialog box & string resources are in edtrcdll DLL
  40. #include "edtrcdll\src\resource.h"
  41.  
  42. // For XP Strings
  43. extern "C" {
  44. #include "xpgetstr.h"
  45. #define WANT_ENUM_STRING_IDS
  46. #include "allxpstr.h"
  47. #undef WANT_ENUM_STRING_IDS
  48. }
  49.  
  50. #ifdef _DEBUG
  51. #undef THIS_FILE
  52. static char BASED_CODE THIS_FILE[] = __FILE__;
  53. #endif
  54.  
  55. // Font shared by all comboboxes in dialogs and toolbars
  56. // Should be 1-pixel, 8pt MS Sans Serif or default GUI or font on foreign systems
  57. CFont * wfe_pFont = 0;
  58. int     wfe_iFontHeight = 15; // Full Height of the this font
  59.  
  60. // Modification of wfe_iFontHeight for list boxes;
  61. int     wfe_iListItemHeight = 15;
  62.  
  63.  
  64. extern void wfe_Progress(MWContext *pMWContext, const char *pMessage);
  65.  
  66. extern BOOL FE_ResolveLinkURL( MWContext* pMWContext, 
  67.                                CString& csURL, BOOL bAutoAdjustLinks );
  68.  
  69. BOOL bSaveDefaultHRule = TRUE;
  70.  
  71. int32 wfe_iFontSizeMode = ED_FONTSIZE_POINTS;
  72.  
  73. // Convert CString into non-const char*
  74. #define CHAR_STR(csString)       (char*)LPCSTR(csString)
  75.  
  76. #define MAX_AUTO_SAVE_MINUTES  600
  77.  
  78. #define COLORREF_SIZE  sizeof(COLORREF)
  79.  
  80. // Array of colors to show in common color dialog
  81. COLORREF wfe_CustomPalette[16];
  82. COLORREF wfe_crLastColorPicked;
  83.  
  84. int wfe_iTrueTypeFontBase = 0;
  85. int wfe_iTrueTypeFontCount = 0;
  86.  
  87. // Global array of True-Type fonts
  88. // Neccesitates restarting program after new fonts installed
  89. char **wfe_ppTrueTypeFonts = NULL;
  90.  
  91. // Global index within wfe_ppTrueTypeFonts if "Other..." was needed (too many fonts)
  92. int wfe_iFontFaceOtherIndex = 0;
  93.  
  94. int CALLBACK EXPORT
  95. EnumTrueTypeFonts(LPLOGFONT lpnlf, LPTEXTMETRIC lpntm, int nFontType, LPARAM lParam)
  96. {
  97.     if (lpntm->tmPitchAndFamily & (/*TMPF_VECTOR|TMPF_DEVICE|*/TMPF_TRUETYPE)){
  98.         if( wfe_iTrueTypeFontCount < MAX_TRUETYPE_FONTS ){
  99.             wfe_ppTrueTypeFonts[wfe_iTrueTypeFontCount] = XP_STRDUP(lpnlf->lfFaceName);
  100.             wfe_iTrueTypeFontCount++;
  101.         } else {
  102.             // Too many fonts -- add "Other..." to use common dialog
  103.             *((BOOL*)lParam) = TRUE;
  104.             return FALSE;
  105.         }
  106.     }
  107.     return TRUE;
  108. }
  109.  
  110. int CompareStrings( const void *arg1, const void *arg2 )
  111. {
  112.    // Compare all of both strings:
  113.    // TODO: DO WIDE/MULTIBYTE VERSION
  114.    return _stricmp( * ( char** ) arg1, * ( char** ) arg2 );
  115. }
  116.  
  117. static BOOL bTooManyFonts = FALSE;
  118.  
  119. BOOL wfe_InitTrueTypeArray(CDC *pDC)
  120. {
  121.     ASSERT(pDC);
  122.     HDC hdc = pDC->GetSafeHdc();
  123.     if( wfe_ppTrueTypeFonts ){
  124.         return bTooManyFonts;
  125.     }
  126.  
  127.     wfe_iTrueTypeFontCount = 0;
  128.     wfe_iFontFaceOtherIndex = 0;
  129.     bTooManyFonts = FALSE;    
  130.     wfe_ppTrueTypeFonts = (char**)XP_ALLOC(MAX_TRUETYPE_FONTS*sizeof(char*));
  131.     if( !wfe_ppTrueTypeFonts ){
  132.         ASSERT(wfe_ppTrueTypeFonts);
  133.         bTooManyFonts = TRUE;
  134.         return TRUE;
  135.     }
  136.     memset((void*)wfe_ppTrueTypeFonts, 0, MAX_TRUETYPE_FONTS*sizeof(char*));
  137.  
  138.     EnumFontFamilies(hdc, NULL, (FONTENUMPROC)EnumTrueTypeFonts, (LPARAM)&bTooManyFonts);
  139.  
  140.     if( wfe_iTrueTypeFontCount ){
  141.         // Sort font names using Quicksort algorithm:
  142.         qsort( (void *)wfe_ppTrueTypeFonts, (size_t)wfe_iTrueTypeFontCount, sizeof( char * ), CompareStrings );
  143.     }
  144.     return bTooManyFonts;
  145. }
  146.  
  147. void wfe_FreeTrueTypeArray()
  148. {
  149.     int i;
  150.     if( wfe_ppTrueTypeFonts ){
  151.         for( i = 0; i < MAX_TRUETYPE_FONTS; i++ ){
  152.             XP_FREEIF(wfe_ppTrueTypeFonts[i]);
  153.         }
  154.         XP_FREE(wfe_ppTrueTypeFonts);
  155.         wfe_ppTrueTypeFonts = 0;
  156.     }
  157.     wfe_iTrueTypeFontCount = 0;
  158. }
  159.  
  160. char pSepFont1[128] = "_";
  161. char pSepFont2[128] = "_";
  162.  
  163. int wfe_FillFontComboBox(CComboBox * pCombo, int * pMaxWidth)
  164. {
  165.     char * pFontFaces = EDT_GetFontFaces();
  166.     CDC * pDC = pCombo->GetDC();
  167.     if( !pDC ) return 0;
  168.     HDC hdc = 0;
  169.     if( pMaxWidth ){
  170.         // We need this only if returning iMaxWidth
  171.         hdc = pDC->GetSafeHdc();
  172.     }
  173.     
  174.     CSize cSize;
  175.     int iMaxWidth = 0;
  176.     int i = 0;
  177.  
  178.     if( pFontFaces ){
  179.         char * pFont = pFontFaces;
  180.         int iLen;    
  181.         for ( i = 0; i < 2; i++){
  182.         
  183.             iLen = XP_STRLEN(pFont);
  184.             if( iLen ){
  185.                 // add to the end of the list
  186.                 // LIST MUST BE NOT SORTED for EDT_GetFontFaceIndex to work
  187.                 if( i == 1 ){
  188.                     // Add signal to draw separator under this string
  189.                     strcpy(pSepFont1+1,pFont);
  190.                     pCombo->AddString(pSepFont1);
  191.                 } else {
  192.                     pCombo->AddString(pFont);
  193.                 }
  194.                 if ( hdc ){            
  195.                     cSize = CIntlWin::GetTextExtent(0, hdc, pFont, strlen(pFont));
  196.                     pDC->LPtoDP(&cSize);
  197.                     if ( cSize.cx > iMaxWidth ){
  198.                         iMaxWidth = cSize.cx;
  199.                     }
  200.                 }
  201.                 pFont += iLen+1;
  202.             } else {
  203.                 break;
  204.             }
  205.         }
  206.     }
  207.     // Done with built-in fonts -- next index must be start of True Type
  208.     wfe_iTrueTypeFontBase = i;
  209.     
  210.     // Get pointers to array of font names
  211.     // (Global list should already be built)
  212.     if( wfe_iTrueTypeFontCount && wfe_ppTrueTypeFonts){
  213.         // Add sorted string list to combobox
  214.         for( int i = 0; i < wfe_iTrueTypeFontCount; i++ ){
  215.             char * pFontName = wfe_ppTrueTypeFonts[i];
  216.             pCombo->AddString(pFontName);
  217.             if ( hdc ){            
  218.                 cSize = CIntlWin::GetTextExtent(0, hdc, pFontName, strlen(pFontName));
  219.                 pDC->LPtoDP(&cSize);
  220.                 if ( cSize.cx > iMaxWidth ){
  221.                     iMaxWidth = cSize.cx;
  222.                 }
  223.             }
  224.         } 
  225.     } else {
  226.         // Should never get here if wfe_IntTrueTypeArray was ever called
  227.         bTooManyFonts = TRUE;;
  228.     }
  229.     if( pMaxWidth ){
  230.         // Return max width so dropdown list can be expanded to fit
  231.         *pMaxWidth = iMaxWidth;
  232.     }
  233.  
  234.     if( bTooManyFonts ){
  235.         // Add pointer to globalb "Other..." string
  236.         pCombo->AddString(ed_pOther);
  237.         // Calculage the index to the "Other..." item,
  238.         wfe_iFontFaceOtherIndex = wfe_iTrueTypeFontBase + wfe_iTrueTypeFontCount;
  239.     } else {
  240.         wfe_iFontFaceOtherIndex = 0;
  241.     }
  242.     pCombo->ReleaseDC(pDC);
  243.     return wfe_iFontFaceOtherIndex;
  244. }
  245.  
  246. char wfe_pFontSizeString[64];
  247. char wfe_pFontSizeList[MAX_FONT_SIZE+1][64];
  248.  
  249. int wfe_FillFontSizeCombo(MWContext *pMWContext, CNSComboBox * pCombo, BOOL bFixedWidth)
  250. {
  251.     int iFontSize = EDT_GetFontSize(pMWContext);
  252.     if( pMWContext ) {
  253.         // Clear current data
  254.         pCombo->ResetContent();
  255.  
  256.         // Format a string like: "+2" for advanced mode, or convert to
  257.         //  point size for regular mode
  258.         for ( int i = 1; i < MAX_FONT_SIZE; i++ ){
  259.             pCombo->AddString(wfe_GetFontSizeString(pMWContext, i, bFixedWidth));
  260.         }
  261.         if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ){
  262.             // "_" will signal combobox to draw a separator under this
  263.             pCombo->AddString("_+4");
  264.             pCombo->AddString("8");
  265.             pCombo->AddString("9");
  266.             pCombo->AddString("10");
  267.             pCombo->AddString("11");
  268.             pCombo->AddString("12");
  269.             pCombo->AddString("14");
  270.             pCombo->AddString("16");
  271.             pCombo->AddString("18");
  272.             pCombo->AddString("20");
  273.             pCombo->AddString("22");
  274.             pCombo->AddString("24");
  275.             pCombo->AddString("26");
  276.             pCombo->AddString("28");
  277.             pCombo->AddString("36");
  278.             pCombo->AddString("48");
  279.             pCombo->AddString("72");
  280.         } else {
  281.             pCombo->AddString(wfe_GetFontSizeString(pMWContext, MAX_FONT_SIZE, bFixedWidth));
  282.         }
  283.     }
  284.     // Index to current size is 1 less than our relative size (range = 1-7)
  285.     // Note that this may be 0 (on startup)
  286.     return (iFontSize - 1);
  287. }
  288.  
  289. // iSize should be  1 to 7
  290. // Returns pointer to static string - DON'T FREE RESULT!
  291. char * wfe_GetFontSizeString(MWContext * pMWContext, int iSize, BOOL bFixedWidth, BOOL bMenu)
  292. {
  293.     ASSERT(pMWContext);
  294.     int iRelative = iSize - 1 + MIN_FONT_SIZE_RELATIVE;
  295.  
  296.     CString csFormat;
  297.  
  298.     if( wfe_iFontSizeMode != ED_FONTSIZE_POINTS ){
  299.         if ( iRelative < 0 ){
  300.             // Minus is very narrow - include extra leading space
  301.             csFormat = " -";
  302.         } else if ( iRelative > 0 ){
  303.             csFormat = '+';
  304.         } else {
  305.             // Use 2 spaces befor "0"; has same width as 1 "-" or "+" char
  306.             csFormat = "  ";
  307.         }
  308.  
  309.         if( bMenu && iSize > 2 ){
  310.             // Add underline for "accelerator" only for "0" and above
  311.             csFormat += '&';
  312.         }
  313.         csFormat += "%i";
  314.  
  315.         wsprintf(wfe_pFontSizeList[iSize-1], LPCSTR(csFormat), abs(iRelative));
  316.     } else {
  317.         // Contstruct strings for Point sizes
  318.         CDCCX *pDC = VOID2CX(pMWContext->fe.cx, CDCCX);
  319.  
  320.         EncodingInfo *pEncoding = theApp.m_pIntlFont->GetEncodingInfo(pMWContext);
  321.         int iBaseSize = bFixedWidth ? pEncoding->iFixSize : pEncoding->iPropSize;
  322.         double dPoints = pDC->CalcFontPointSize(iSize, iBaseSize);
  323.         wsprintf(wfe_pFontSizeList[iSize-1], "%d", (int)dPoints);
  324.     }
  325.     return wfe_pFontSizeList[iSize-1];
  326. }
  327.  
  328. ////////////////////////////////////////////////////////////////////////
  329. // Local string helper functions
  330.  
  331. // Strip out quotes and spaces at the ends
  332. void CleanupString(CString& csString)
  333. {
  334.     csString.TrimLeft();
  335.     csString.TrimRight();
  336.     int iQuote;    
  337.     while ( (iQuote = csString.Find('\"')) != -1 ){
  338.         csString = csString.Left(iQuote) + csString.Mid(iQuote+1);
  339.     }
  340. }
  341.  
  342. // Extract separate Name and Value strings
  343. // Return TRUE if Name string was found
  344. BOOL GetNameAndValue(CString& csEntry, CString& csName, CString& csValue)
  345. {
  346.     int iEqual = csEntry.Find('=');
  347.     if ( iEqual != -1 ) {
  348.         csName = csEntry.Left(iEqual);
  349.         CleanupString(csName);
  350.         csValue = csEntry.Mid(iEqual+1);
  351.         CleanupString(csValue);
  352.         return ( !csName.IsEmpty() );
  353.     }
  354.     return FALSE;
  355. }
  356.  
  357. // Local function used by Image and Document Properties dialogs
  358. //
  359. BOOL wfe_ValidateImage(MWContext * pMWContext, CString& csImageURL, BOOL bCheckIfFileExists)
  360. {
  361.     BOOL   bRetVal = TRUE;
  362.     BOOL   bFileExists = FALSE;
  363.     CleanupString(csImageURL);
  364.     char * pAbsoluteImageURL = NULL;
  365.     CString csURL;
  366.  
  367.     // Empty is OK
  368.     if ( csImageURL.IsEmpty() ) {
  369.         return TRUE;
  370.     }
  371.     //int   iUrlType = NET_URL_Type(csUrl);
  372.  
  373.     // We will trust HTTP: URLs to be absolute and valid
  374.     if ( NET_IsHTTP_URL( csImageURL ) ) {
  375.         return TRUE;
  376.     }        
  377.  
  378.     // Convert to URL format -- just copies if already have URL syntax
  379.     WFE_ConvertFile2Url( csURL, (char*)LPCSTR(csImageURL) );
  380.  
  381.     // Convert any user-enterred local strings to an absolute URL
  382.     History_entry * pEntry = SHIST_GetCurrent(&pMWContext->hist);
  383.     if( pEntry && pEntry->address ) {
  384.         pAbsoluteImageURL = NET_MakeAbsoluteURL( 
  385.                                 pEntry->address, (char *)LPCSTR(csURL) );
  386.     }
  387.  
  388.     if(bCheckIfFileExists && pAbsoluteImageURL) {
  389.  
  390.         if ( NET_IsLocalFileURL((char*)LPCSTR(csImageURL)) ) {
  391.             // We have a local file URL -- test for existence
  392.              char * pLocal = NULL;
  393.              bFileExists = XP_ConvertUrlToLocalFile( csImageURL, &pLocal /*NULL*/);
  394.              if( pLocal ) XP_FREE(pLocal);
  395.  
  396.         } else {
  397.             // Assume we have a local file - find it
  398.             XP_StatStruct statinfo;
  399.             if ( -1 != XP_Stat((char*)LPCSTR(csImageURL), &statinfo, xpURL) &&
  400.                 statinfo.st_mode & _S_IFREG ) {
  401.                 bFileExists = TRUE;
  402.             }
  403.         }
  404.         if ( !bFileExists ) {
  405.             CString csMsg;
  406.             AfxFormatString1(csMsg, IDS_ERR_SRC_NOT_FOUND, csImageURL);  
  407.             CWnd *pParent = GetFrame(pMWContext)->GetFrameWnd()->GetLastActivePopup();
  408.             ::MessageBox( pParent ? pParent->m_hWnd : NULL, 
  409.                           csMsg, szLoadString(IDS_VALIDATE_IMAGE_FILE),
  410.                           MB_OK | MB_ICONEXCLAMATION);
  411.         }
  412.     }
  413.  
  414.     if( bCheckIfFileExists ){
  415.         bRetVal = bFileExists;
  416.     }
  417.     
  418.     if ( pAbsoluteImageURL ) {
  419.         if( bRetVal ){
  420.             csImageURL = pAbsoluteImageURL;
  421.         }
  422.         XP_FREE(pAbsoluteImageURL);
  423.     }
  424.  
  425.     return bRetVal;
  426. }
  427.  
  428. // Initialize the strings for percent/pixels combobox
  429. //   used with Width and Height input
  430. void wfe_InitPixOrPercentCombos(CWnd* pParent)
  431. {
  432.     CComboBox *pCombo = 
  433.         (CComboBox*)(pParent->GetDlgItem(IDC_HEIGHT_PIX_OR_PERCENT));
  434.     if(pCombo){
  435.         pCombo->AddString(szLoadString(IDS_PIXELS));
  436.         pCombo->AddString(szLoadString(IDS_PERCENT_WINDOW));
  437.     }
  438.     pCombo = (CComboBox*)(pParent->GetDlgItem(IDC_WIDTH_PIX_OR_PERCENT));
  439.     if(pCombo){
  440.         pCombo->AddString(szLoadString(IDS_PIXELS));
  441.         pCombo->AddString(szLoadString(IDS_PERCENT_WINDOW));
  442.     }
  443. }
  444.  
  445. // Get the "100%" Height and "100%" Width that layout uses:
  446. //  this is the current view's dimensions minus margins
  447. void wfe_GetLayoutViewSize(MWContext * pMWContext, int32 * pWidth, int32 * pHeight)
  448. {
  449.     if( pMWContext ){
  450.         int32 iXOrigin;
  451.         int32 iYOrigin;
  452.         int32 iHeight;
  453.         int32 iWidth;
  454.         int32 iMarginWidth;
  455.         int32 iMarginHeight;
  456.  
  457.         FE_GetDocAndWindowPosition(pMWContext, &iXOrigin, &iYOrigin, &iWidth, &iHeight);
  458.         LO_GetDocumentMargins(pMWContext, &iMarginWidth, &iMarginHeight);
  459.  
  460.         if( pWidth ){
  461.             *pWidth = iWidth - (2 * iMarginWidth);
  462.         }
  463.         if( pHeight ){
  464.             *pHeight = iHeight - (2 * iMarginHeight);
  465.         }
  466.     }    
  467. }
  468.  
  469.  
  470. char * wfe_ConvertImage(char *p_fileurl,void *p_parentwindow,MWContext *p_pMWContext)
  471. {
  472.     if( !wfe_ValidateImage(p_pMWContext, CString(p_fileurl), TRUE) ){
  473.         return NULL;
  474.     }
  475.  
  476.     CONVERT_IMGCONTEXT imageContext;
  477.     CONVERT_IMG_INFO imageInfo;
  478.     memset(&imageContext,0,sizeof(CONVERT_IMGCONTEXT));
  479.     imageContext.m_stream.m_type=CONVERT_FILE;
  480.     char *t_charp;
  481.     XP_ConvertUrlToLocalFile(p_fileurl,&t_charp);
  482.     if (!t_charp) //failed to localize file
  483.     {
  484.         // Show same error message as when wfe_ValidateImage fails:
  485.         CString csMsg;
  486.         AfxFormatString1(csMsg, IDS_ERR_SRC_NOT_FOUND, p_fileurl);  
  487.         CWnd *pParent = GetFrame(p_pMWContext)->GetFrameWnd()->GetLastActivePopup();
  488.         ::MessageBox( pParent ? pParent->m_hWnd : NULL, 
  489.                       csMsg, szLoadString(IDS_VALIDATE_IMAGE_FILE),
  490.                       MB_OK | MB_ICONEXCLAMATION);
  491.         return NULL;
  492.     }
  493.     XP_STRCPY(imageContext.m_filename,t_charp);
  494.     XP_FREE(t_charp);
  495.     imageContext.m_stream.m_file=XP_FileOpen(imageContext.m_filename,xpTemporary,XP_FILE_READ_BIN);
  496.     if (imageContext.m_stream.m_file)
  497.     {
  498.         imageContext.m_imagetype=conv_bmp;
  499.         imageContext.m_callbacks.m_dialogimagecallback=FE_ImageConvertDialog;
  500.         imageContext.m_callbacks.m_displaybuffercallback=FE_ImageConvertDisplayBuffer;
  501.         imageContext.m_callbacks.m_completecallback=NULL;
  502.  
  503.         imageContext.m_pMWContext=p_pMWContext;
  504.         imageContext.m_parentwindow=p_parentwindow;
  505.         char *t_outputfilename[1];
  506.         t_outputfilename[0]=NULL;
  507.         CONVERT_IMAGERESULT t_result=convert_stream2image(imageContext,&imageInfo,1,t_outputfilename); //1 for 1 output
  508.         //there is a callback when complete 
  509.         XP_FileClose(imageContext.m_stream.m_file);
  510.         if (t_outputfilename[0])
  511.         {
  512.             // If using GIF plugin, wait here until finished
  513.             //   (edit buffer is not writeable during plugin use)
  514.             char * pLastDot = strrchr(t_outputfilename[0], '.');
  515.             if(pLastDot && 0 == _stricmp(pLastDot, ".gif")){
  516.                 while(!EDT_IsWritableBuffer(p_pMWContext)) FEU_StayingAlive();
  517.             }
  518.             return t_outputfilename[0];
  519.         }
  520.         else
  521.         {
  522.             if (t_result>CONV_OK)//not cancel or ok
  523.             {
  524.                 ((CWnd *)p_parentwindow)->MessageBox(szLoadString(CNetscapeEditView::m_converrmsg[t_result]));
  525.             }
  526.             return NULL;
  527.         }
  528.     }
  529.     return NULL;
  530. }
  531.  
  532.  
  533.  
  534. CNSComboBox::CNSComboBox() :
  535.     m_iSearchPos(0),
  536.     m_bAllowSearch(0),
  537.     m_dwButtonDownTime(0),
  538.     m_bCheckTime(0),
  539.     m_pNotInListText(0)
  540. {
  541. }
  542.  
  543. BOOL CNSComboBox::Create(RECT& rect, CWnd* pParentWnd, UINT nID)
  544. {
  545.     if( !CComboBox::Create(CBS_DROPDOWNLIST|CBS_OWNERDRAWFIXED|WS_VISIBLE|WS_TABSTOP|WS_VSCROLL|WS_HSCROLL|CBS_AUTOHSCROLL,
  546.                            rect, pParentWnd, nID) ){
  547.         TRACE0("Failed to create Netscape Combo-box\n");
  548.         return FALSE;
  549.     }
  550.  
  551.     if( wfe_pFont )
  552.         SetFont(wfe_pFont);
  553.  
  554.     return TRUE;    
  555. }
  556.  
  557. BOOL CNSComboBox::Subclass(CWnd* pParentWnd, UINT nID)
  558. {
  559.     BOOL bResult = SubclassDlgItem(nID, pParentWnd);
  560.     if( bResult ){
  561.         if( wfe_pFont )
  562.             SetFont(wfe_pFont);
  563.     }
  564.     return bResult;
  565. }
  566.  
  567. int CNSComboBox::FindSelectedOrSetText(char * pText, int iStartAt)
  568. {
  569.     int iSel = -1;
  570.     if( pText ){
  571.         // Skip over initial signal for separator
  572.         if( *pText == '_' ){
  573.             pText++;
  574.         }
  575.         for( int i = iStartAt; i < GetCount(); i++ ){
  576.             char * pItem = (char*)GetItemData(i);
  577.             if( *pItem == '_' ){
  578.                 pItem++;
  579.             }
  580.             if( 0 == strcmp(pText, pItem) ){
  581.                 // We found it
  582.                 iSel = i;
  583.                 break;
  584.             }
  585.         }
  586.         if( iSel == -1 ){
  587.             // Text is not in the list
  588.             XP_FREEIF(m_pNotInListText);
  589.             m_pNotInListText = XP_STRDUP(pText);
  590.         }
  591.         SetCurSel(iSel);
  592.         // SetCurSel doesn't display text!
  593.         SetWindowText(pText);
  594.     } else {
  595.         SetWindowText("");
  596.     }
  597.     return iSel;
  598. }
  599.  
  600. void CNSComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
  601. {
  602.     // all items are of fixed size
  603.     lpMIS->itemHeight = wfe_iListItemHeight;
  604. }
  605.  
  606. //////////////////////////////////////////////////////////////
  607. void CNSComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  608. {
  609.     CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  610.  
  611.     CRect rectItem  = lpDIS->rcItem;
  612.  
  613.     if( lpDIS->itemState & ODS_SELECTED ){
  614.         pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
  615.         pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
  616.     } else {
  617.         pDC->SetTextColor(RGB(0,0,0));
  618.         pDC->SetBkColor(RGB(255,255,255));
  619.     }
  620.     
  621.     char *pData;
  622.     if( lpDIS->itemData == -1){// When is this -1?
  623.         // This is a real neat trick to display text in closed
  624.         //   dropdown combobox's main window even though
  625.         //   text is not in list (selected item = -1)
  626.         // This text should be set in FindSelectedOrSetText
  627.         pData = m_pNotInListText;
  628.     } else {
  629.         pData = (char*)lpDIS->itemData;
  630.     }
  631.     
  632.     if( pData ){
  633.         // Draw a gray line separator
  634.         CPen pen(PS_SOLID, 1, RGB(128,128,128));
  635.         CPen *pOldPen = pDC->SelectObject(&pen);
  636.  
  637.         BOOL bDrawSeparator = FALSE;
  638.         if( *pData == '_' ){
  639.             // We have a separator - skip over signal character
  640.             pData++;
  641.             if( GetDroppedState() ) {
  642.                 bDrawSeparator = TRUE;
  643.             }
  644.         }
  645.         pDC->ExtTextOut(4, rectItem.top+1, ETO_CLIPPED | ETO_OPAQUE, &lpDIS->rcItem,
  646.                         pData, strlen(pData), NULL);
  647.         if( bDrawSeparator ){
  648.             // Draw solid line as separator
  649.             pDC->MoveTo(rectItem.left, rectItem.bottom-1);
  650.             pDC->LineTo(rectItem.right, rectItem.bottom-1);
  651.         }
  652.         pDC->SelectObject(pOldPen);
  653.     }
  654. }
  655.  
  656. int CNSComboBox::CompareItem(LPCOMPAREITEMSTRUCT lpCIS)
  657. {
  658.     // We should never sort!
  659.     return 0;
  660. }
  661.  
  662. // These were initially in CEditFrame:
  663. BEGIN_MESSAGE_MAP(CNSComboBox, CComboBox)
  664.     //{{AFX_MSG_MAP(CNSComboBox)
  665.     ON_WM_KEYDOWN()
  666.     //}}AFX_MSG_MAP
  667. END_MESSAGE_MAP()
  668.  
  669. void CNSComboBox::InitSearch()
  670. {
  671.     // Don't allow autoselect while typing 
  672.     //   when we have a multibyte system
  673.     if( !GetSystemMetrics(SM_DBCSENABLED) ){
  674.         m_bAllowSearch = TRUE;
  675.         m_iSearchPos = 0;
  676.         m_pSearchBuf[m_iSearchPos] = '\0';
  677.     }
  678. }
  679.  
  680. void CNSComboBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  681. {
  682.     BOOL bMatch;
  683.     // Ignor shift and control presses
  684.     if( m_bAllowSearch && nChar != VK_SHIFT && nChar != VK_CONTROL ){
  685.         if( nChar != VK_RETURN && 
  686.             (nChar == 4 || XP_IS_ALPHA(nChar) ||
  687.              XP_IS_DIGIT(nChar) || XP_IS_SPACE(nChar)) )
  688.         {
  689.             int iStart = 0;
  690.             if( nChar == VK_BACK ){
  691.                 // Backup/delete key in buffer
  692.                 if( m_iSearchPos > 0 ){
  693.                     m_iSearchPos--;
  694.                 }
  695.             } else {
  696.                 // Append acceptable character to search buffer
  697.                 m_pSearchBuf[m_iSearchPos] = nChar;
  698.                 if( m_iSearchPos ){
  699.                     // Start search from current item if we already had a string,
  700.                   iStart = GetCurSel();
  701.                 }
  702.                 m_iSearchPos++;
  703.             }
  704.             m_pSearchBuf[m_iSearchPos] = '\0';
  705.  
  706.             for( int i = iStart; i < GetCount(); i++ )
  707.             {
  708.                 char * pItem = (char*)GetItemData(i);
  709.                 if( *pItem == '_' ){
  710.                     pItem++;
  711.                 }
  712.                 if( strlen(pItem) >= (size_t)m_iSearchPos ){
  713.                     // Current item is at least as long, so compare
  714.                     // 
  715.                     char save = pItem[m_iSearchPos];
  716.                     pItem[m_iSearchPos] = '\0';
  717.                     bMatch = ( 0 == stricmp(pItem, m_pSearchBuf) );
  718.                     // Restore
  719.                     pItem[m_iSearchPos] = save;
  720.                     if( bMatch ){
  721.                         // We found it - set selection
  722.                         SetCurSel(i);
  723.                         break;
  724.                     }
  725.                 }
  726.             }
  727.             if( !bMatch ){
  728.                 // We didn't find next char, so backup
  729.                 m_iSearchPos--;
  730.                 m_pSearchBuf[m_iSearchPos] = '\0';
  731.             }
  732.         } else {
  733.             // Another other key resets the search string
  734.             m_iSearchPos = 0;
  735.             m_pSearchBuf[m_iSearchPos] = '\0';
  736.         }
  737.     }
  738.     CComboBox::OnKeyDown(nChar, nRepCnt, nFlags);
  739. }
  740.  
  741. BOOL CNSComboBox::PreTranslateMessage(MSG* pMsg)
  742. {
  743.     return CComboBox::PreTranslateMessage(pMsg);
  744. }
  745.  
  746. /////////////////////////////////////////////////////////////////////////////////////
  747. // Netscape Color string for Default Text color
  748. char pDefaultFontColorString[256] = "";
  749. // COLORREF equivalent
  750. COLORREF crDefaultColor;
  751.  
  752. char pDefaultNoColorString[256] = "";
  753.  
  754. char * wfe_GetDefaultColorString(COLORREF crColor)
  755. {
  756.     if( crColor == NO_COLORREF){
  757.         if( *pDefaultNoColorString == '\0' ){
  758.             strcpy(pDefaultNoColorString, szLoadString(IDS_DEFAULT_NOCOLOR));
  759.         }
  760.         crDefaultColor = RGB(255,255,255);
  761.         return pDefaultNoColorString;
  762.     } 
  763.  
  764.     if( crColor == DEFAULT_COLORREF ){
  765.         // Get default text color
  766.         PREF_GetDefaultColorPrefDWord("browser.foreground_color", &crDefaultColor);
  767.     } else {
  768.         // Use the supplied color
  769.         crDefaultColor = crColor;
  770.     }
  771.  
  772.     sprintf(pDefaultFontColorString,"%d,%d%,%d,%s", 
  773.             GetRValue(crDefaultColor),
  774.             GetGValue(crDefaultColor),
  775.             GetBValue(crDefaultColor), 
  776.             szLoadString(IDS_DEFAULT));
  777.  
  778.     return pDefaultFontColorString;
  779. }
  780.  
  781. /////////////////////////////////////////////////////////////////////////////
  782. // Custom Combobox - containing colors
  783.  
  784. CColorComboBox::CColorComboBox() :
  785.     m_crColor(MIXED_COLORREF),
  786.     m_bCustomColor(0),
  787.     m_bMixedColors(0),
  788.     m_hPal(0),
  789.     m_pParent(0)
  790. {
  791. }
  792.  
  793. BEGIN_MESSAGE_MAP(CColorComboBox, CComboBox)
  794.     //{{AFX_MSG_MAP(CColorComboBox)
  795.       ON_WM_LBUTTONDOWN()
  796.     ON_WM_LBUTTONUP()
  797.     ON_WM_LBUTTONDBLCLK()
  798.     //}}AFX_MSG_MAP
  799. END_MESSAGE_MAP()
  800.  
  801. void CColorComboBox::OnLButtonDown(UINT nFlags, CPoint cPoint)
  802. {
  803.     if( m_pParent ){
  804.         // Send message to parent to do the Color Dialog
  805.         m_pParent->SendMessage(WM_COMMAND, ID_GET_COLOR, 0);
  806.     }
  807. }
  808. void CColorComboBox::OnLButtonUp(UINT nFlags, CPoint cPoint)
  809. {
  810. }
  811. void CColorComboBox::OnLButtonDblClk(UINT nFlags, CPoint cPoint)
  812. {
  813.     if( m_pParent ){
  814.         // Send message to parent to do the Color Dialog
  815.         m_pParent->SendMessage(WM_COMMAND, ID_GET_COLOR, 0);
  816.     }
  817. }
  818.  
  819. int CColorComboBox::SubclassAndFill(CWnd* pParentWnd, UINT nID, COLORREF crDefColor)
  820. {
  821.     m_pParent = pParentWnd;
  822.     if( SubclassDlgItem(nID, pParentWnd) ){
  823.         return FillList(crDefColor);
  824.     }
  825.     return 0;
  826. }
  827.  
  828. BOOL CColorComboBox::CreateAndFill(RECT& rect, CWnd* pParentWnd, UINT nID, COLORREF crDefColor)
  829. {
  830.     m_pParent = pParentWnd;
  831.     if( !Create(CBS_DROPDOWNLIST|CBS_OWNERDRAWFIXED|WS_VISIBLE|WS_TABSTOP|WS_VSCROLL,
  832.                 rect, pParentWnd, nID) ){
  833.         TRACE0("Failed to create Font Color combo-box\n");
  834.         return FALSE;
  835.     }
  836.  
  837.     if( wfe_pFont ){
  838.         SetFont(wfe_pFont);
  839.     }
  840.     return FillList(crDefColor);
  841. }
  842.  
  843. int CColorComboBox::FillList(COLORREF crDefColor)
  844. {
  845.  
  846.     CDC * pDC = GetDC();
  847.     if( !pDC ) return 0;
  848.  
  849.     m_hPal = WFE_GetUIPalette(GetParentFrame());
  850.     
  851.     // WE NO LONGER FILL THE LIST - POPUP IS USED INSTEAD
  852.  
  853.     ReleaseDC(pDC);
  854.     return TRUE;
  855. }
  856.  
  857. void CColorComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
  858. {
  859.     // all items are of fixed size
  860.     lpMIS->itemHeight = wfe_iListItemHeight;
  861. }
  862.  
  863. void CColorComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  864. {
  865.     // We need to draw outside the supplied area,
  866.     // so use main combobox DC
  867.     HDC hDC = GetDC()->m_hDC;
  868.  
  869.     HPALETTE hOldPal = NULL;
  870.     if( m_hPal )
  871.     {
  872.         hOldPal = ::SelectPalette( hDC, m_hPal, FALSE );
  873.     }
  874.  
  875.     RECT rect = lpDIS->rcItem;
  876.     ::InflateRect(&rect, 1, 1);
  877.  
  878.     // Draw color sample 
  879.     if (lpDIS->itemAction & ODA_DRAWENTIRE)
  880.     {
  881.         if( m_bMixedColors )
  882.         {
  883.             rect.top--;
  884.             rect.left--;
  885.             //rect.bottom++;
  886.             ::FillRect(hDC, &rect, sysInfo.m_hbrBtnFace);
  887.             if( sysInfo.m_bWin4 )
  888.             {
  889.                 // It looks very odd unless we add a line to close off button
  890.                 HPEN penShadow = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnShadow);
  891.                 HPEN hPenOld = (HPEN)::SelectObject(hDC, penShadow);
  892.                 ::MoveToEx(hDC, rect.right, rect.top, NULL);
  893.                 ::LineTo(hDC, rect.right, rect.bottom);
  894.                 ::SelectObject(hDC, hPenOld);
  895.                 ::DeleteObject(penShadow);
  896.             }
  897.         } else {
  898.             HBRUSH hBrush = ::CreateSolidBrush(m_crColor|0x02000000); // Like PALETTERGB
  899.             ::FillRect(hDC, &rect, hBrush);
  900.             ::DeleteObject(hBrush);
  901.  
  902.             int32 iColorTotal = GetRValue(m_crColor) + GetGValue(m_crColor) + GetBValue(m_crColor);
  903.  
  904.             COLORREF crColorHighlight = 0;
  905.             if(  iColorTotal < 153 )
  906.                 crColorHighlight = PALETTERGB(255,255,0);
  907.             else if( iColorTotal > 700 )
  908.                 crColorHighlight = PALETTERGB(0,0,255);
  909.  
  910.             if( sysInfo.m_bWin4 )
  911.             {
  912.                 // Extra color highlight if color is too dark or light
  913.                 if( crColorHighlight )
  914.                 {
  915.                     hBrush = ::CreateSolidBrush(crColorHighlight);
  916.                     ::FrameRect(hDC, &rect, hBrush);
  917.                     ::DeleteObject(hBrush);
  918.                 }
  919.             } else {
  920.                 // Older UIs have a flat-look for comboboxes,
  921.                 //  and need an extra border here
  922.                 //  And we use color if current color is too dark or bright
  923.                 if( crColorHighlight )
  924.                 {
  925.                     hBrush = ::CreateSolidBrush(crColorHighlight);
  926.                 } else {
  927.                     hBrush = (HBRUSH)::GetStockObject(BLACK_BRUSH);
  928.                 }
  929.                 ::FrameRect(hDC, &rect, hBrush);
  930.  
  931.                 if( crColorHighlight )
  932.                     ::DeleteObject(hBrush);
  933.             } 
  934.         }
  935.     }
  936.     if(m_hPal)
  937.     {
  938.         ::SelectPalette( hDC, hOldPal, FALSE );
  939.     }
  940.     ::ReleaseDC(this->m_hWnd, hDC);
  941. }
  942.  
  943. int CColorComboBox::CompareItem(LPCOMPAREITEMSTRUCT lpCIS)
  944. {
  945.     // We should never sort!
  946.     return 0;
  947. }
  948.  
  949. int CColorComboBox::SetColor(COLORREF cr)
  950. {
  951.     int iIndex = -1;
  952.     if( cr == MIXED_COLORREF )
  953.     {
  954.         m_crColor = RGB(255,255,255);
  955.     }else if( cr == DEFAULT_COLORREF )
  956.     {
  957.         m_crColor = crDefaultColor;
  958.         iIndex = 0;
  959.     } else {
  960.         m_crColor = cr; 
  961.         LO_Color LoColor;
  962.         LoColor.red = GetRValue(cr);
  963.         LoColor.green = GetGValue(cr);
  964.         LoColor.blue = GetBValue(cr);
  965.         iIndex = EDT_GetMatchingFontColorIndex(&LoColor);
  966.     }
  967.     m_bMixedColors = (cr == MIXED_COLORREF);
  968.     // Custom color is one not in our list
  969.     m_bCustomColor = !m_bMixedColors && iIndex == -1;
  970.     Invalidate(FALSE);
  971.     SetCurSel(iIndex);
  972.     return iIndex;
  973. }
  974.  
  975.  
  976. #define COLOR_ROWS 7
  977. #define COLOR_COLS 10
  978. #define COLOR_SWATCH_HEIGHT 16
  979. #define COLOR_SWATCH_WIDTH  18
  980. #define COLOR_SWATCH_SPACING 0
  981. #define COLOR_SWATCH_TOP         (COLOR_SWATCH_HEIGHT + 4)
  982. #define COLOR_PICKER_HEIGHT      (((COLOR_ROWS + 6)*COLOR_SWATCH_HEIGHT) + 26)
  983. #define COLOR_PICKER_WIDTH       (COLOR_COLS*COLOR_SWATCH_WIDTH + 7)
  984. #define BUTTON_WIDTH        (4*COLOR_SWATCH_WIDTH - 4)
  985.  
  986. // Index to the first USER custom color, which follows the Netscape colors
  987. //   (first custom color, the "last-used" is actually 0 in color array)
  988. // Add 1 for the Last-Used color swatch above main color grid
  989. //   and another for the "Current color" swatch above quick palette
  990. #define FIRST_CUSTOM_COLOR_INDEX (MAX_NS_COLORS + 2)
  991.  
  992. ////////////////////////////////////////////////////////////////////////////////////////////
  993. // CColorPicker     Widget for picking colors
  994. // We can't use Pretranslate or SetCapture under Win16, 
  995. //  so we must derive from CWnd, not CDialog
  996.  
  997. CColorPicker::CColorPicker(CWnd      * pParent,
  998.                      MWContext * pMWContext,
  999.                      COLORREF    crCurrentColor,
  1000.                      COLORREF    crDefColor,
  1001.                      UINT        nIDCaption,
  1002.                      RECT      * pCallerRect)
  1003.     : CWnd(),
  1004.       m_pParent(pParent),
  1005.       m_pMWContext(pMWContext),
  1006.       m_crCurrentColor(crCurrentColor),
  1007.       m_crDefColor(crDefColor),
  1008.       m_nIDCaption(nIDCaption),
  1009.       m_pToolTip(0),
  1010.       m_bOtherDown(0),
  1011.       m_bAutoDown(0),
  1012.       m_bHelpDown(0),
  1013.       m_bRunning(TRUE),
  1014.       m_bFirstMouseUp(TRUE),
  1015.       m_bMouseDown(FALSE),
  1016.       m_crDragColor(0)
  1017. {
  1018.     POINT ptOrigin;
  1019.  
  1020.     if( pCallerRect )
  1021.     {
  1022.         m_CallerRect = *pCallerRect;
  1023.     } else {
  1024.         m_CallerRect.left = m_CallerRect.right = m_CallerRect.top = m_CallerRect.bottom = 0;
  1025.     }
  1026.     m_LoColor.red = m_LoColor.green = m_LoColor.blue = 0;
  1027.     
  1028.     // If current is DEFAULT (i.e. "Automatic"), get appropriate default color
  1029.     if( m_crCurrentColor == DEFAULT_COLORREF )
  1030.     {
  1031.         if( crDefColor == DEFAULT_COLORREF || crDefColor == MIXED_COLORREF )
  1032.         {
  1033.             // Get the "Default" color used by the Browser
  1034.             COLORREF tmpColor,defColor;
  1035.             XP_Bool bCust;
  1036.             PREF_GetColorPrefDWord("browser.foreground_color",&tmpColor);
  1037.             PREF_GetDefaultColorPrefDWord("browser.foreground_color",&defColor);
  1038.             PREF_GetBoolPref("browser.custom_text_color",&bCust);
  1039.             m_crCurrentColor = bCust ? tmpColor : defColor;
  1040.         } else if( crDefColor == BACKGROUND_COLORREF )
  1041.         {
  1042.  
  1043.             // Get current page's background color
  1044.             //   as "default" for table backgrounds
  1045.             CDCCX *pDC = VOID2CX(pMWContext->fe.cx, CDCCX);
  1046.             m_crCurrentColor = pDC->m_rgbBackgroundColor;
  1047.         } else
  1048.         {
  1049.             // Use the default color supplied
  1050.             m_crCurrentColor = crDefColor;
  1051.         }
  1052.     }  
  1053.    
  1054.     if( m_CallerRect.left == 0 && m_CallerRect.top == 0 )
  1055.     {
  1056.         // No caller rect supplied - locate top at cursor Y and 
  1057.         // X so cursor pt. is at horizontal center
  1058.         GetCursorPos(&ptOrigin);
  1059.         ptOrigin.x -= (ED_TB_BUTTON_WIDTH / 2);
  1060.     } else {
  1061.         // The -1 lines up light highlight with that of parent
  1062.         ptOrigin.x = m_CallerRect.left - 1;
  1063.         // We may change this below if near bottom of screen
  1064.         ptOrigin.y = m_CallerRect.bottom;
  1065.     }
  1066.  
  1067.     if (!CWnd::CreateEx(WS_EX_TOPMOST, 
  1068.                         AfxRegisterWndClass(CS_SAVEBITS | CS_VREDRAW,
  1069.                                             ::LoadCursor( NULL, IDC_ARROW),
  1070.                                             sysInfo.m_hbrBtnFace),
  1071.                         NULL, WS_POPUP /*| WS_VISIBLE*/ | WS_DLGFRAME,
  1072.                         ptOrigin.x, ptOrigin.y,
  1073.                         COLOR_PICKER_WIDTH, COLOR_PICKER_HEIGHT,
  1074.                         pParent->m_hWnd, NULL, NULL))
  1075.     {
  1076.         TRACE0("Warning: creation of CColorPicker window failed\n");
  1077.         return;
  1078.     }
  1079.     
  1080.     SetFont(wfe_pFont);
  1081.  
  1082.     // Add a tooltip control
  1083.     m_pToolTip = new CNSToolTip2;
  1084.  
  1085.     if(m_pToolTip && !m_pToolTip->Create(this, TTS_ALWAYSTIP) )
  1086.     {
  1087.        TRACE("Unable To create ToolTip\n");
  1088.        delete m_pToolTip;
  1089.        m_pToolTip = NULL;
  1090.     } else {
  1091.         // Lets use speedy tooltips
  1092.         m_pToolTip->SetDelayTime(200);
  1093. #ifdef XP_WIN32
  1094.         // We MUST do this for MFC tooltips
  1095.         EnableToolTips(TRUE);
  1096. #endif // WIN32
  1097.     }
  1098.  
  1099.     int iTop = 2;
  1100.     int iCustomTop;
  1101.     int iLeft = 4;
  1102.     int iCol = 0;
  1103.     int iRow = 0;
  1104.     int iRowLimit = COLOR_ROWS - 1; // Doesn't include custom colors
  1105.     //int iXPOffset = 0;
  1106.     int iCustomColor = 0; // Counter for custom colors
  1107.  
  1108.     RECT rectOther; // For the "Other..." button
  1109.     RECT rect;
  1110.     RECT rectLabel;
  1111.     char *pLabel;   // Holds static pointer for szLoadString (dont free)
  1112.  
  1113.     for( int i = 0; i < MAX_COLORS; i++ )
  1114.     {
  1115.            LO_Color LoColor;
  1116.  
  1117.         if( i > 0 && i <= MAX_NS_COLORS ) // in main color grid
  1118.         {
  1119.             // Set top to be used for all colors in main region
  1120.             iTop = COLOR_SWATCH_TOP;
  1121.             EDT_GetNSColor(i-1, &LoColor);
  1122.             m_crColors[i] = RGB(LoColor.red, LoColor.green, LoColor.blue);
  1123.         } 
  1124.         else
  1125.         {
  1126.             if( i == 0 )
  1127.             {                
  1128.                 // The very first Custom color is actually the "last-used" color
  1129.                 m_crColors[i] = wfe_crLastColorPicked;
  1130.  
  1131.                 pLabel = szLoadString(IDS_LAST_USED_COLOR);
  1132.                 rectLabel.top = iTop + 1;
  1133.                 rectLabel.left = COLOR_SWATCH_WIDTH + 2;
  1134.                 rectLabel.right = COLOR_PICKER_WIDTH;
  1135.                 rectLabel. bottom = rectLabel.top + COLOR_SWATCH_HEIGHT;
  1136.                 if( !m_LastUsedLabel.Create(pLabel, WS_VISIBLE | WS_CHILD, rectLabel, this) )
  1137.                     return;
  1138.             }
  1139.             else if( i == MAX_NS_COLORS+1 ) // Should = FIRST_CUSTOM_COLOR_INDEX-1
  1140.             {
  1141.                 // Current color swatch just below the main colors
  1142.                 m_crColors[i] = m_crCurrentColor;
  1143.  
  1144.                 // Set text label next to this color swatch
  1145.                 pLabel = szLoadString(IDS_CURRENT_COLOR);
  1146.  
  1147.                 iTop = COLOR_SWATCH_TOP + (COLOR_ROWS * COLOR_SWATCH_HEIGHT) + 2;
  1148.                 rectLabel.top = iTop + 1;
  1149.                 rectLabel.left = COLOR_SWATCH_WIDTH + 2;
  1150.                 rectLabel.right = COLOR_PICKER_WIDTH - 6 - BUTTON_WIDTH;
  1151.                 rectLabel. bottom = rectLabel.top + COLOR_SWATCH_HEIGHT;
  1152.                 if( !m_CurrentLabel.Create(pLabel, WS_VISIBLE | WS_CHILD, rectLabel, this) )
  1153.                     return;
  1154.                 iCol = 0;
  1155.                 iRow = 0;
  1156.             }
  1157.             else if( i >= FIRST_CUSTOM_COLOR_INDEX )
  1158.             {                
  1159.                 // Get custom colors from global palette
  1160.                 m_crColors[i] = wfe_CustomPalette[iCustomColor++];
  1161.  
  1162.                 if( i == FIRST_CUSTOM_COLOR_INDEX )
  1163.                 {
  1164.                     // Add the "Automatic" button ( = "Default", i.e., no color in HTML)
  1165.                     //   at the same vertical location as "Current color" swatch
  1166.                     //  (Must create here to get tab order correct)
  1167.                     rectOther.top = iTop + 2;
  1168.                     rectOther.bottom = rectOther.top + 22;
  1169.                     rectOther.right = COLOR_PICKER_WIDTH - 8;
  1170.                     rectOther.left = rectOther.right - BUTTON_WIDTH;
  1171.  
  1172.                     m_OtherButton.Create(szLoadString(IDS_OTHER_BUTTON), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
  1173.                                          rectOther, this, IDC_CHOOSE_COLOR); 
  1174.                 
  1175.                     // TODO: ADD A TOOLTIP FOR "AUTO" BUTTON for added instructions?
  1176.                     
  1177.                     // Label above custom colors:
  1178.                     pLabel = szLoadString(IDS_CUSTOM_COLORS_LABEL);
  1179.                     rectLabel.left = 2;
  1180.                     rectLabel.right = rectOther.left - 1;
  1181.                     rectLabel.top = iTop + COLOR_SWATCH_HEIGHT + 2;
  1182.                     // We cut 2 pixels off font height for tighter fit (TODO: PROBLEM IN OTHER LANGUAGES?)
  1183.                     rectLabel.bottom = rectLabel.top + wfe_iFontHeight - 2;
  1184.                     if( !m_CustomColorsLabel.Create(pLabel, WS_VISIBLE | WS_CHILD, rectLabel, this) )
  1185.                         return;
  1186.         
  1187.                     // Top of custom colors row - place just below label
  1188.                     iTop = iCustomTop = rectLabel.bottom;
  1189.                     iCol = 0;
  1190.                     iRow = 0;
  1191.                 }
  1192.             }
  1193.             LoColor.red = GetRValue(m_crColors[i]);
  1194.             LoColor.green = GetGValue(m_crColors[i]);
  1195.             LoColor.blue = GetBValue(m_crColors[i]);
  1196.         }
  1197.  
  1198.         rect.left = iCol*COLOR_SWATCH_WIDTH;
  1199.         rect.top = iTop + (iRow*COLOR_SWATCH_HEIGHT);
  1200.         rect.right = rect.left + COLOR_SWATCH_WIDTH;
  1201.         rect.bottom = rect.top + COLOR_SWATCH_HEIGHT;
  1202.  
  1203.         // Create our custom buttons
  1204.         m_pColorButtons[i] = new CColorButton(&m_crColors[i], &m_crColor);
  1205.         if( !m_pColorButtons[i] ||
  1206.             !m_pColorButtons[i]->Create(rect, this, IDC_LAST_USED_COLOR+i, &m_crColors[i], TRUE) )
  1207.         {
  1208.             return;
  1209.         }
  1210.         // Add tooltip showing color formated as "R=xxx G=xxx B=xxx  HTML: #FFEEAA"
  1211.         if( m_pToolTip )
  1212.         {
  1213.             if( m_crColors[i] == DEFAULT_COLORREF )
  1214.             {
  1215.                 *m_ppTipText[i] = 0;
  1216.             } else 
  1217.             {
  1218.                 wsprintf(m_ppTipText[i], szLoadString(IDS_COLOR_TIP_FORMAT),
  1219.                          LoColor.red, LoColor.green, LoColor.blue);
  1220.                 strcat(m_ppTipText[i], szLoadString(IDS_COLOR_TIP_HTML));
  1221.                 char * pEnd = m_ppTipText[i] + strlen(m_ppTipText[i]);
  1222.                 sprintf(pEnd, "#%02X%02X%02X",LoColor.red, LoColor.green, LoColor.blue);
  1223.  
  1224.                 m_pToolTip->AddTool(m_pColorButtons[i], m_ppTipText[i], &rect, IDC_LAST_USED_COLOR+i);
  1225.             }
  1226.         }
  1227.  
  1228.         if( i >= FIRST_CUSTOM_COLOR_INDEX )
  1229.         {
  1230.             // We are within single custom color row
  1231.             iCol++;
  1232.         }
  1233.         else if( i > 0 )
  1234.         {
  1235.             // Main color grid
  1236.             // Add each button in columns first, add new column after every 7
  1237.             if(iRow < iRowLimit)
  1238.             {
  1239.                 iRow++;
  1240.             } else {
  1241.                 iRow = 0;
  1242.                 iCol++;
  1243.             }
  1244.         }
  1245.     }
  1246.  
  1247.     // Add Number strings under custom color swatches
  1248.     rect.left = 6;
  1249.     rect.top = iCustomTop + COLOR_SWATCH_HEIGHT;
  1250.     rect.bottom = rect.top + COLOR_SWATCH_HEIGHT;
  1251.  
  1252.     for( i = 0; i < MAX_CUSTOM_COLORS; i++  )
  1253.     {
  1254.         rect.right = rect.left + COLOR_SWATCH_WIDTH;
  1255.         char pNumber[16];
  1256.         wsprintf(pNumber, "%d", (i < MAX_CUSTOM_COLORS-1) ? i+1 : 0);
  1257.         if( !m_CustomColorNumber[i].Create(pNumber, WS_VISIBLE | WS_CHILD, rect, this) )
  1258.             return;
  1259.         // Move to next location
  1260.         rect.left += COLOR_SWATCH_WIDTH;
  1261.     }
  1262.  
  1263.     // Place "Browser default" button in lower left corner:    
  1264.     rect.top = rect.bottom;
  1265.     rect.bottom = rect.top + 22;
  1266.     rect.left = 2;
  1267.     rect.right = rect.left + BUTTON_WIDTH + 2*COLOR_SWATCH_WIDTH; // BUTTON_WIDTH
  1268.  
  1269.     m_DefaultButton.Create(szLoadString(IDS_DEFAULT_BUTTON), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
  1270.                                         rect, this, IDC_DEFAULT_COLOR); 
  1271.     
  1272.     // Now we can determine bottom of entire window
  1273.     // Number added to this must be enough for 2 lines of text (this is now 30)
  1274.     // This is weird, but adding about 4 results in same place as "Other" button button,
  1275.     //  seems like button is larger than 24???
  1276.     int iTotalHeight = rect.bottom + 8;
  1277.  
  1278.     // Place "Help" color button in lower right corner:    
  1279.     rect.right = COLOR_PICKER_WIDTH - 8;
  1280.     rect.left = rect.right - BUTTON_WIDTH;
  1281.     // NOTE: IDS_HELP_BUTTON string is in Browser resources
  1282.     m_HelpButton.Create(szLoadString(IDS_HELP_BUTTON), BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
  1283.                          rect, this, IDC_COLOR_HELP); 
  1284.     
  1285.  
  1286.     // Set this so color doesn't change if no interaction?
  1287.     m_crColor = WFE_GetCurrentFontColor(m_pMWContext);
  1288.  
  1289.     // Set our font for all static strings used
  1290.     if( wfe_pFont )
  1291.     {
  1292.         // Set the font to our usual 8-pt font
  1293.         m_OtherButton.SetFont(wfe_pFont);
  1294.         m_HelpButton.SetFont(wfe_pFont);
  1295.         m_LastUsedLabel.SetFont(wfe_pFont);
  1296.         m_CurrentLabel.SetFont(wfe_pFont);
  1297.         m_DefaultButton.SetFont(wfe_pFont);
  1298.         m_CustomColorsLabel.SetFont(wfe_pFont);
  1299.         for( int i = 0; i < MAX_CUSTOM_COLORS; i++ )
  1300.         {
  1301.             m_CustomColorNumber[i].SetFont(wfe_pFont);
  1302.         }
  1303.     }
  1304.     
  1305.     // Check if we need to move up because we would go off the screen
  1306.     if( (m_CallerRect.bottom + iTotalHeight) > sysInfo.m_iScreenHeight )
  1307.     {
  1308.         // Locate toolbar above the caller button
  1309.         //   if toolbar bottom would extend off bottom of screen
  1310.         ptOrigin.y = m_CallerRect.top - iTotalHeight;
  1311.     }
  1312.     // Move and/or resize the window and show it for the first time
  1313.     SetWindowPos(NULL, ptOrigin.x, ptOrigin.y, COLOR_PICKER_WIDTH, iTotalHeight, SWP_SHOWWINDOW );
  1314.  
  1315.     // Capture mouse so we can detect clicking off the dialog
  1316.     SetCapture();
  1317.     // Restore active caption highlighting to parent frame
  1318.     GetParentFrame()->SetActiveWindow();
  1319. }
  1320.  
  1321. COLORREF crReturnColor;
  1322.  
  1323. // Call this instead of DoModal() to wait in dialog and get result
  1324. COLORREF CColorPicker::GetColor(LO_Color * pLoColor)
  1325. {
  1326.  
  1327.     // Wait here until user selects a color or
  1328.     //   cancels the dialog with ESC or by clicking outside window
  1329.     while( m_bRunning ) FEU_StayingAlive();
  1330.  
  1331.     // Return selected or custom color
  1332.     if( pLoColor )
  1333.     {
  1334.         pLoColor->red = m_LoColor.red;
  1335.         pLoColor->green = m_LoColor.green;
  1336.         pLoColor->blue = m_LoColor.blue;
  1337.     }
  1338.     crReturnColor = m_crColor;
  1339.     DestroyWindow();
  1340.     return crReturnColor;
  1341. }
  1342.  
  1343. void CColorPicker::SetColorAndExit()
  1344. {
  1345.     if( m_crColor != DEFAULT_COLORREF )
  1346.     {
  1347.         m_LoColor.red = GetRValue(m_crColor);
  1348.         m_LoColor.green = GetGValue(m_crColor);
  1349.         m_LoColor.blue = GetBValue(m_crColor);
  1350.     }
  1351.     // Set flag that will let us return to caller and destroy dialog
  1352.     m_bRunning = FALSE;
  1353. }
  1354.  
  1355. void CColorPicker::CancelAndExit()
  1356. {
  1357.     m_crColor = CANCEL_COLORREF;
  1358.     m_bRunning = FALSE;
  1359. }
  1360.  
  1361. CColorPicker::~CColorPicker()
  1362. {
  1363. }
  1364.  
  1365. void CColorPicker::PostNcDestroy() 
  1366. {
  1367.     char pPref[32];
  1368.     char pColorString[32];
  1369.  
  1370.     // Save the last-picked color
  1371.     wsprintf(pColorString, "%d,%d,%d", GetRValue(wfe_crLastColorPicked), GetGValue(wfe_crLastColorPicked), GetBValue(wfe_crLastColorPicked));
  1372.     PREF_SetCharPref("editor.last_color_picked", pColorString);
  1373.  
  1374.     // Save custom colors back to prefs
  1375.     for ( int i = 0; i < MAX_CUSTOM_COLORS; i++ )
  1376.     {
  1377.         // Write new pref only if different than original value
  1378.         if( m_bColorChanged[i] )
  1379.         {
  1380.             COLORREF crColor = wfe_CustomPalette[i]; // should = m_crColors[iColorIndex];
  1381.             wsprintf(pColorString, "%d,%d,%d", GetRValue(crColor), GetGValue(crColor), GetBValue(crColor));
  1382.             wsprintf(pPref, "editor.custom_color_%d", i);
  1383.             PREF_SetCharPref(pPref, pColorString);
  1384.         }
  1385.     }
  1386.  
  1387.     if( m_pToolTip )
  1388.         delete m_pToolTip;
  1389.  
  1390.      ReleaseCapture();
  1391.     CWnd::PostNcDestroy();
  1392. }
  1393.  
  1394. BEGIN_MESSAGE_MAP(CColorPicker, CWnd)
  1395.     //{{AFX_MSG_MAP(CColorPicker)
  1396.     ON_WM_LBUTTONUP()
  1397.       ON_WM_LBUTTONDOWN()
  1398.     ON_WM_MOUSEMOVE()
  1399.     //}}AFX_MSG_MAP
  1400. #ifdef XP_WIN32
  1401.     ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
  1402. #endif
  1403. END_MESSAGE_MAP()
  1404.  
  1405. BOOL CColorPicker::PreTranslateMessage(MSG* pMsg)
  1406. {
  1407.     if( m_pToolTip && pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
  1408.     {
  1409.         m_pToolTip->RelayEvent(pMsg);
  1410.     }
  1411.     if( pMsg->message == WM_KEYDOWN )
  1412.     {
  1413.         if( pMsg->wParam == VK_ESCAPE )
  1414.         {
  1415.             CancelAndExit();
  1416.         } 
  1417.         else if( pMsg->wParam == VK_F1 )
  1418.         {
  1419.             OnColorHelp();
  1420.         }
  1421.         else 
  1422.         {
  1423.             // Are any number keys pressed?
  1424.             // This is 1 less than number on key pressed
  1425.             int iNumberIndex = pMsg->wParam - '1';
  1426.             // "0" key is AFTER "9" on keyboard
  1427.             //   so treat it like a 10th color
  1428.             if( iNumberIndex == -1 )
  1429.                 iNumberIndex = 9;
  1430.  
  1431.             if( iNumberIndex >= 0 && iNumberIndex <= 9 ) // This won't work if MAX_CUSTOM_COLORS > 10
  1432.             {
  1433.                 // Set the current focus color at the custom color matching number
  1434.                 m_crColors[FIRST_CUSTOM_COLOR_INDEX+iNumberIndex] = m_crColor;
  1435.                 m_pColorButtons[FIRST_CUSTOM_COLOR_INDEX+iNumberIndex]->Invalidate(FALSE);
  1436.             }
  1437.         }
  1438.     }
  1439.     return CWnd::PreTranslateMessage(pMsg);
  1440. }
  1441.  
  1442. BOOL CColorPicker::IsMouseOverDlg(CPoint cPoint)
  1443. {
  1444.     CRect cRect;
  1445.     GetWindowRect(&cRect);
  1446.     ScreenToClient(&cRect);
  1447.     return cRect.PtInRect(cPoint);
  1448. }
  1449.  
  1450. BOOL CColorPicker::IsMouseOverButton(CPoint cPoint, UINT nID)
  1451. {
  1452.     CRect cRect;
  1453.     ((CButton*)GetDlgItem(nID))->GetWindowRect(&cRect);
  1454.     ScreenToClient(&cRect);
  1455.     return cRect.PtInRect(cPoint);
  1456. }
  1457.  
  1458. int CColorPicker::GetMouseOverColorIndex(CPoint cPoint)
  1459. {
  1460.     CRect cRect;
  1461.     for( int i = 0; i < MAX_COLORS; i++){
  1462.         GetDlgItem(IDC_LAST_USED_COLOR+i)->GetWindowRect(&cRect);
  1463.         ScreenToClient(&cRect);
  1464.         if( cRect.PtInRect(cPoint) ){
  1465.             // Select the color and return the index
  1466.             //  unless it is "default" (unknown)
  1467.             if( m_crColors[i] != DEFAULT_COLORREF )
  1468.             {
  1469.                 m_crColor = m_crColors[i];
  1470.                 return i;
  1471.             }
  1472.         }
  1473.     }
  1474.     return -1;
  1475. }
  1476.  
  1477. void CColorPicker::OnLButtonDown(UINT nFlags, CPoint cPoint)
  1478. {
  1479.     POINT pt = {cPoint.x,cPoint.y};
  1480.     // If user clicks outside of dialog, we are done
  1481.     if( !IsMouseOverDlg(cPoint) ){
  1482.         CancelAndExit();
  1483.         return;
  1484.     }
  1485.  
  1486.     if( IsMouseOverButton(cPoint, IDC_CHOOSE_COLOR) && !m_bOtherDown ){
  1487.         m_bOtherDown = TRUE;
  1488.         ((CButton*)GetDlgItem(IDC_CHOOSE_COLOR))->SetState(TRUE);
  1489.     } else if( IsMouseOverButton(cPoint, IDC_DEFAULT_COLOR) && !m_bAutoDown ){
  1490.         m_bAutoDown = TRUE;
  1491.         ((CButton*)GetDlgItem(IDC_DEFAULT_COLOR))->SetState(TRUE);
  1492.     } else if( IsMouseOverButton(cPoint, IDC_COLOR_HELP) && !m_bHelpDown ){
  1493.         m_bHelpDown = TRUE;
  1494.         ((CButton*)GetDlgItem(IDC_COLOR_HELP))->SetState(TRUE);
  1495.     }
  1496.     
  1497.     // Copy color for possible dragging
  1498.     int i = GetMouseOverColorIndex(cPoint);
  1499.     if( i >= 0 ){
  1500.         m_crDragColor = m_crColors[i];
  1501.         m_bMouseDown = TRUE;
  1502.         m_iMouseDownColorIndex = i;
  1503.  
  1504.         SetCursor(theApp.LoadCursor(IDC_DRAG_COLOR));
  1505.     }
  1506.     CWnd::OnLButtonDown(nFlags, cPoint);
  1507. }
  1508.  
  1509. void CColorPicker::OnLButtonUp(UINT nFlags, CPoint cPoint)
  1510. {
  1511.     // We get this when user "dragged" over combobox to trigger
  1512.     //  dialog, then move away and let mouse up. Quit just like combo-list would
  1513.     if( !IsMouseOverDlg(cPoint) )
  1514.     {
  1515.         // But check if over the caller rect
  1516.         CRect cRect(m_CallerRect);
  1517.         ScreenToClient(&cRect);
  1518.         if( !cRect.PtInRect(cPoint) )
  1519.         {
  1520.             CancelAndExit();
  1521.             return;
  1522.         }
  1523.     } else {
  1524.         // Detect mouse up on a color swatch select it
  1525.         //  or drop copied color
  1526.         int i = GetMouseOverColorIndex(cPoint);
  1527.  
  1528.         // Ignore first mouse up on current color
  1529.         if( i == 0 && m_bFirstMouseUp )
  1530.             return;
  1531.  
  1532.         m_bFirstMouseUp = FALSE;
  1533.  
  1534.         if( i >= 0 )
  1535.         {
  1536.             if( m_bMouseDown && i >= FIRST_CUSTOM_COLOR_INDEX &&
  1537.                 m_iMouseDownColorIndex != i) // TRUE when click down/up to select quick color
  1538.             {
  1539.                 // We are dropping a color onto custom palette
  1540.                 m_crColors[i] = m_crDragColor;
  1541.                 int iCustomIndex = i - FIRST_CUSTOM_COLOR_INDEX;
  1542.                 wfe_CustomPalette[iCustomIndex] = m_crDragColor;
  1543.                 m_bColorChanged[iCustomIndex] = TRUE;
  1544.  
  1545.                 // Force redraw
  1546.                 m_pColorButtons[i]->Invalidate(FALSE);
  1547.             } else if( !m_bMouseDown || m_iMouseDownColorIndex == i )
  1548.             {
  1549.                 // Button came up in same color as mouse down,
  1550.                 //  or up when not dragging is not possible
  1551.                 //  because mouse was already down when picker started
  1552.                 m_crColor = m_crColors[i];
  1553.                 // Always save selected color as the "last color picked"
  1554.                 wfe_crLastColorPicked = m_crColor;
  1555.                 SetColorAndExit();
  1556.                 return;
  1557.             }
  1558.             // We dropped color or didn't select,
  1559.             //  but we must be over a color swatch,
  1560.             //  so set appropriate cursor
  1561.             SetCursor(theApp.LoadCursor(IDC_DRAG_ARROW));
  1562.         }
  1563.  
  1564.         if( IsMouseOverButton(cPoint, IDC_CHOOSE_COLOR) )
  1565.         {
  1566.             OnChooseColor();
  1567.             return;
  1568.         }
  1569.         if( IsMouseOverButton(cPoint, IDC_DEFAULT_COLOR) )
  1570.         {
  1571.             OnDefaultColor();
  1572.             return;
  1573.         }
  1574.         if( IsMouseOverButton(cPoint, IDC_COLOR_HELP) )
  1575.         {
  1576.             ((CButton*)GetDlgItem(IDC_COLOR_HELP))->SetState(FALSE);
  1577.             m_bHelpDown = FALSE;
  1578.             OnColorHelp();
  1579.         }
  1580.     }
  1581.     m_bMouseDown = FALSE;
  1582.     CWnd::OnLButtonUp(nFlags, cPoint);    
  1583. }
  1584.  
  1585. void CColorPicker::SetButtonState(CPoint cPoint, UINT nID, BOOL* pButtonDown )
  1586. {
  1587.     BOOL bOverButton = IsMouseOverButton(cPoint, nID);
  1588.  
  1589.     if( !bOverButton && *pButtonDown)
  1590.     {
  1591.         // Deselect button when mouse moves off
  1592.         *pButtonDown = FALSE;
  1593.         ((CButton*)GetDlgItem(nID))->SetState(FALSE);
  1594.     } else if( bOverButton && !*pButtonDown /*&& (nFlags & MK_LBUTTON)*/ )
  1595.     {
  1596.         *pButtonDown = TRUE;
  1597.         ((CButton*)GetDlgItem(nID))->SetState(TRUE);
  1598.     }
  1599. }
  1600.  
  1601. void CColorPicker::OnMouseMove(UINT nFlags, CPoint cPoint)
  1602. {
  1603.     int i = GetMouseOverColorIndex(cPoint);
  1604.     if( i != 0 )
  1605.     {
  1606.         // If not over Current Color button,
  1607.         //   kill ignore-on-first-mouseup behavior
  1608.         m_bFirstMouseUp = FALSE;
  1609.     }
  1610.  
  1611.     // Set button shade state to act like normal dialog button
  1612.     //  when mouse is held down
  1613.     if( nFlags & MK_LBUTTON )
  1614.     {
  1615.         SetButtonState(cPoint, IDC_CHOOSE_COLOR, &m_bOtherDown);    
  1616.         SetButtonState(cPoint, IDC_DEFAULT_COLOR, &m_bAutoDown);    
  1617.         SetButtonState(cPoint, IDC_COLOR_HELP, &m_bHelpDown);    
  1618.     }
  1619.  
  1620.     if( m_bMouseDown )
  1621.     {
  1622.         // Give user feedback via cursor
  1623.         UINT nIDC;
  1624.         if( m_iMouseDownColorIndex == i )
  1625.             // Over source swatch - NULL icon is confusing - show arrow + color box
  1626.             nIDC = IDC_DRAG_COLOR;
  1627.         else if( i >= FIRST_CUSTOM_COLOR_INDEX )
  1628.             // Over drop target
  1629.             nIDC = IDC_DROP_COLOR;
  1630.         else 
  1631.             // Over anything else - can't drop
  1632.             nIDC = IDC_NO_DROP;
  1633.  
  1634.         SetCursor(theApp.LoadCursor(nIDC));
  1635.     } else {
  1636.         if( i >= 0 )
  1637.         {
  1638.             // Tells user they can drag a color
  1639.             SetCursor(theApp.LoadCursor(IDC_DRAG_ARROW));
  1640.             if( GetFocus() != m_pColorButtons[i] )
  1641.             {
  1642.                 // Bring focus to color where mouse is
  1643.                 m_pColorButtons[i]->SetFocus();
  1644.                 m_crColor = m_crColors[i];
  1645.             }
  1646.         }
  1647.         else
  1648.         {
  1649.             // Not over color or dragging - regular cursor
  1650.             SetCursor(theApp.LoadStandardCursor(IDC_ARROW));
  1651.         }
  1652.     }
  1653.     CWnd::OnMouseMove(nFlags, cPoint);    
  1654. }
  1655.  
  1656. // 
  1657. #ifdef XP_WIN32 
  1658. // This is needed for non-CFrame owners of a CToolTipCtrl
  1659. BOOL CColorPicker::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
  1660. {
  1661.     TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
  1662.     UINT nID =pNMHDR->idFrom;
  1663.     if (pTTT->uFlags & TTF_IDISHWND)
  1664.     {
  1665.         // idFrom is actually the HWND of the tool
  1666.         nID = ::GetDlgCtrlID((HWND)nID);
  1667.         if( nID ) {
  1668.             int i = nID - IDC_LAST_USED_COLOR;
  1669.             if( i >= 0 && i < MAX_COLORS && m_ppTipText[i] ){
  1670.                 // Copy string into buffer - limit is 80 characters
  1671.                 strcpy( pTTT->szText, m_ppTipText[i]);
  1672.                 return(TRUE);
  1673.             }
  1674.         }
  1675.     }
  1676.     return(FALSE);
  1677. }
  1678. #endif
  1679.  
  1680. void CColorPicker::OnDefaultColor()
  1681. {
  1682.     m_crColor = DEFAULT_COLORREF;
  1683.  
  1684.     SetColorAndExit();
  1685. }
  1686.  
  1687. // Select any color via Window's color dialog
  1688. void CColorPicker::OnChooseColor()
  1689. {
  1690.     // Use CC_PREVENTFULLOPEN in flags (2nd) param if we want to suppress editing
  1691.        CColorDialog dlg(wfe_CustomPalette[0], CC_FULLOPEN, this);
  1692.     
  1693.     // Place our current palette into the 16 Custom colors
  1694.     // Copy colors so we don't change anything if 
  1695.     COLORREF crCustomColors[16];
  1696.     memcpy((void*)crCustomColors, (void*)wfe_CustomPalette, sizeof(crCustomColors));
  1697.     
  1698.     dlg.m_cc.lpCustColors = crCustomColors;
  1699.     dlg.m_cc.lStructSize = sizeof( dlg.m_cc );
  1700.  
  1701.     // TODO: We need to make a derived class to control common dialog palette 
  1702.     //  or do hook for WM_INTDIALOG in m_cc struct
  1703.     //  so we can set the palette of the Window's CColorDlg
  1704.  
  1705.     UINT nResult = dlg.DoModal();
  1706.  
  1707.     if( nResult == IDOK ){
  1708.         m_crColor = dlg.GetColor();
  1709.         // Save this color as last color picked
  1710.         wfe_crLastColorPicked = m_crColor;
  1711.         // Copy custom colors back to global palette
  1712.         memcpy((void*)wfe_CustomPalette, (void*)crCustomColors, sizeof(crCustomColors));
  1713.         m_bColorChanged[0] = TRUE;
  1714.         SetColorAndExit();
  1715.     } else {
  1716.         CancelAndExit();
  1717.     }
  1718. }
  1719.  
  1720. void CColorPicker::OnColorHelp()
  1721. {
  1722.     NetHelp(HELP_COLOR_PICKER);
  1723. }
  1724.  
  1725. /////////////////////////////////////////////////////////////////////////////
  1726. // CDropdownToolbar  Popup window with thin border to place a vertical row of buttons
  1727.  
  1728. CDropdownToolbar::CDropdownToolbar(CWnd      * pParent,
  1729.                                    MWContext * pMWContext,
  1730.                                    RECT      * pCallerRect,
  1731.                                    UINT      nCallerID,
  1732.                                    UINT      nInitialID)
  1733.     : CWnd(),
  1734.       m_pParent(pParent),
  1735.       m_pMWContext(pMWContext),
  1736.       m_nCallerID(nCallerID),
  1737.       m_nInitialID(nInitialID),
  1738.       m_nButtonCount(0),
  1739.       m_nAllocatedCount(0),
  1740.       m_pData(NULL),
  1741.       m_pToolTip(0),
  1742.       m_bFirstButtonUp(TRUE)
  1743. {
  1744.     if( pCallerRect ){
  1745.         m_CallerRect = *pCallerRect;
  1746.     } else {
  1747.         m_CallerRect.left = m_CallerRect.right = m_CallerRect.top = m_CallerRect.bottom = 0;
  1748.     }
  1749.  
  1750.     if (!CWnd::CreateEx(WS_EX_TOPMOST, AfxRegisterWndClass(CS_SAVEBITS | CS_VREDRAW, ::LoadCursor( NULL, IDC_ARROW)),
  1751.                       NULL, WS_POPUP | WS_BORDER /*|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS*/,
  1752.                       0, 0, 0, 0, pParent->m_hWnd, NULL, NULL))
  1753.     {
  1754.         TRACE0("Warning: creation of CDropdownToolbar window failed\n");
  1755.         return;
  1756.     }
  1757.  
  1758.     // Add a tooltip control
  1759.     m_pToolTip = new CNSToolTip2;
  1760.  
  1761.     if(m_pToolTip && !m_pToolTip->Create(this, TTS_ALWAYSTIP) ){
  1762.        TRACE("Unable To create ToolTip\n");
  1763.        delete m_pToolTip;
  1764.        m_pToolTip = NULL;
  1765.     }
  1766.     if( m_pToolTip ){
  1767.         m_pToolTip->Activate(TRUE);
  1768.         // Lets use speedy tooltips
  1769.         m_pToolTip->SetDelayTime(50);
  1770. #ifdef XP_WIN32
  1771.         // We MUST do this for MFC tooltips
  1772.         EnableToolTips(TRUE);
  1773. #endif // WIN32
  1774.     }
  1775. }
  1776.  
  1777. CDropdownToolbar::~CDropdownToolbar()
  1778. {
  1779.     if( m_pData ){
  1780.         for( UINT i = 0; i < m_nButtonCount; i++ ){
  1781.             if( m_pData[i].pButton ){
  1782.                 if( m_pData[i].pButtonName ) XP_FREE((void*)m_pData[i].pButtonName);
  1783.                 delete m_pData[i].pButton;
  1784.             }
  1785.         }
  1786.         XP_FREE( m_pData );
  1787.     }
  1788.     if( m_pToolTip ){
  1789.         delete m_pToolTip;
  1790.     }
  1791. }
  1792.  
  1793. void CDropdownToolbar::PostNcDestroy() 
  1794. {
  1795.     ReleaseCapture();
  1796.     CWnd::PostNcDestroy();
  1797.     delete this;
  1798. }
  1799.  
  1800. // Create a CBitmapPushButton - resource name should be correct form for
  1801. //   a CBitmapButton: "Button_" will load "Button_D.BMP" and "Button_U.BMP"
  1802. //   bitmap files for Down and Up button images.
  1803. BOOL CDropdownToolbar::AddButton(LPSTR pButtonName, UINT nCommandID)
  1804. {
  1805.     ASSERT(pButtonName);
  1806.     ASSERT(nCommandID);
  1807.     if( m_nAllocatedCount < (m_nButtonCount + 1) ){
  1808.         m_nAllocatedCount += 8;
  1809.         m_pData = (DropdownToolbarData*)XP_REALLOC(m_pData,
  1810.                             m_nAllocatedCount * sizeof(DropdownToolbarData));
  1811.     }
  1812.     if( m_pData ){
  1813.         DropdownToolbarData *pData = &m_pData[m_nButtonCount];
  1814.  
  1815.         pData->pButton = new CBitmapPushButton(TRUE); // Use "borderless" button style
  1816.         if( ! pData->pButton ){
  1817.             TRACE0("Failed to allocated new button for DropdownToolbar\n");
  1818.             return FALSE;
  1819.         }
  1820.         pData->nCommandID = nCommandID;
  1821.         pData->nBitmapID = 0;
  1822.         pData->pButtonName = XP_STRDUP(pButtonName);
  1823.     } else {
  1824.         TRACE0("Failed to reallocated new DropdownToolbar data\n");
  1825.         return FALSE;
  1826.     }
  1827.     m_nButtonCount++;
  1828.     return TRUE;
  1829. }
  1830.  
  1831. BOOL CDropdownToolbar::AddButton(UINT nBitmapID, UINT nCommandID)
  1832. {
  1833.     ASSERT(nBitmapID);
  1834.     ASSERT(nCommandID);
  1835.     if( m_nAllocatedCount < (m_nButtonCount + 1) ){
  1836.         m_nAllocatedCount += 8;
  1837.         m_pData = (DropdownToolbarData*)XP_REALLOC(m_pData,
  1838.                             m_nAllocatedCount * sizeof(DropdownToolbarData));
  1839.     }
  1840.     if( m_pData ){
  1841.         DropdownToolbarData *pData = &m_pData[m_nButtonCount];
  1842.  
  1843.         pData->pButton = new CBitmapPushButton(TRUE); // Use "borderless" button style
  1844.         if( ! pData->pButton ){
  1845.             TRACE0("Failed to allocated new button for DropdownToolbar\n");
  1846.             return FALSE;
  1847.         }
  1848.         pData->nCommandID = nCommandID;
  1849.         pData->pButtonName = NULL;
  1850.         pData->nBitmapID = nBitmapID;
  1851.     
  1852.     } else {
  1853.         TRACE0("Failed to reallocated new DropdownToolbar data\n");
  1854.         return FALSE;
  1855.     }
  1856.     m_nButtonCount++;
  1857.     return TRUE;
  1858. }
  1859.  
  1860. // Call this AFTER adding all buttons to toolbaar
  1861. void CDropdownToolbar::Show()
  1862. {
  1863.     if( m_nButtonCount == 0 )
  1864.         return;
  1865.  
  1866.     // Full height of toolbar frame
  1867.     int   iHeight = (ED_TB_BUTTON_HEIGHT * m_nButtonCount) + 2;
  1868.     POINT ptOrigin;
  1869.     
  1870.     if( m_CallerRect.left == 0 && m_CallerRect.top == 0 ){
  1871.         // No caller rect supplied - locate top at cursor Y and 
  1872.         // X so cursor pt. is at horizontal center
  1873.         GetCursorPos(&ptOrigin);
  1874.         ptOrigin.x -= (ED_TB_BUTTON_WIDTH / 2);
  1875.  
  1876.     } else {
  1877.         // Minus 1 for the 1-pixel dialog border around dropdown
  1878.         //  (makes dropdown look centered under caller button)
  1879.         ptOrigin.x = m_CallerRect.left + ((m_CallerRect.right - m_CallerRect.left - ED_TB_BUTTON_WIDTH) / 2);
  1880.         
  1881.         if( (m_CallerRect.bottom + iHeight) > sysInfo.m_iScreenHeight ){
  1882.             // Locate toolbar above the caller button
  1883.             //   if toolbar bottom would extend off bottom of screen
  1884.             ptOrigin.y = m_CallerRect.top - iHeight;
  1885.         } else {
  1886.             ptOrigin.y = m_CallerRect.bottom;
  1887.         }
  1888.     }
  1889.  
  1890.     // Set location and size (fits tight around all buttons)
  1891.     SetWindowPos( &wndTopMost, ptOrigin.x, ptOrigin.y,
  1892.                   ED_TB_BUTTON_WIDTH + 2, iHeight, SWP_NOACTIVATE );
  1893.     
  1894.     // Convert caller rect to toolbar's coordinates
  1895.     //  to use for mouse hit testing
  1896.     if( m_CallerRect.left != 0 && m_CallerRect.top != 0 ){
  1897.         ScreenToClient(&m_CallerRect);
  1898.     }
  1899.  
  1900.     // Create all the buttons and load bitmaps etc
  1901.     if( m_pData && m_nButtonCount > 0 ){
  1902.         DropdownToolbarData *pData = m_pData;
  1903.         RECT rect = {0, 0, ED_TB_BUTTON_WIDTH, ED_TB_BUTTON_HEIGHT-1};
  1904.  
  1905.         for( UINT i = 0; i < m_nButtonCount; i++, pData++ ){
  1906.             UINT nStyle = BS_PUSHBUTTON | BS_OWNERDRAW | WS_CHILD;
  1907.             if( i == 0 ){
  1908.                 nStyle |= WS_GROUP | WS_TABSTOP;
  1909.             }
  1910.             rect.bottom++;
  1911.             if( ! pData->pButton->Create(pData->pButtonName, nStyle, 
  1912.                                          rect, this, pData->nCommandID) ){
  1913.                 TRACE0("Failed to allocated new button in DropdownToolbar\n");
  1914.         
  1915.             BUTTON_FAILED:
  1916.                 delete pData->pButton;
  1917.                 if( pData->pButtonName ) {
  1918.                     XP_FREE(pData->pButtonName);
  1919.                     pData->pButtonName = NULL;
  1920.                 }
  1921.                 pData->pButton = NULL;
  1922.                 CWnd::DestroyWindow();
  1923.                 return;
  1924.             }
  1925.             rect.bottom--;
  1926.                if( pData->pButtonName) {
  1927.                 CString buttonName(pData->pButtonName);
  1928.                    if( ! pData->pButton->LoadBitmaps(buttonName + _T("U"),
  1929.                                                   buttonName + _T("D"), 0, 0) ){
  1930.                     TRACE0("Failed to load bitmaps for button in DropdownToolbar\n");
  1931.                     goto BUTTON_FAILED;
  1932.                 }
  1933.             } else if( pData->nBitmapID ){
  1934.                 if( ! pData->pButton->LoadBitmap(pData->nBitmapID) ){
  1935.                     TRACE0("Failed to load bitmaps for button in DropdownToolbar\n");
  1936.                     goto BUTTON_FAILED;
  1937.                 }
  1938.             } else {
  1939.                 TRACE0("No bitmap name or ID supplied for button in DropdownToolbar\n");
  1940.                 goto BUTTON_FAILED;
  1941.             }
  1942.             // Set pushed-down state for button if requested
  1943.             if( m_nInitialID > 0 && pData->nCommandID == m_nInitialID ){
  1944.                 pData->pButton->SetCheck(TRUE);
  1945.             }
  1946.             pData->pButton->ShowWindow(SW_SHOW);
  1947.  
  1948.             // Add tooltip for the button
  1949.             if( m_pToolTip ){
  1950. #ifdef XP_WIN16
  1951.                 m_pToolTip->DelTool(pData->pButton->m_hWnd, pData->nCommandID);
  1952. #endif
  1953.                 m_pToolTip->AddTool(pData->pButton, pData->nCommandID,
  1954.                                     &rect, pData->nCommandID);
  1955.             }
  1956.             
  1957.             // Move to next button down
  1958.             rect.top += ED_TB_BUTTON_HEIGHT;
  1959.             rect.bottom += ED_TB_BUTTON_HEIGHT; 
  1960.         }
  1961.         if( m_pToolTip ){
  1962.             m_pToolTip->Activate(TRUE);
  1963.         }
  1964.     }
  1965.     
  1966.     ShowWindow(SW_SHOW);
  1967.     // Grab the mouse so a click outside the dialog closes toolbar
  1968.     SetCapture();
  1969.     // Restore active caption highlighting to parent frame
  1970.     GetParentFrame()->SetActiveWindow();
  1971. }
  1972.  
  1973. BEGIN_MESSAGE_MAP(CDropdownToolbar, CWnd)
  1974.     //{{AFX_MSG_MAP(CDropdownToolbar)
  1975.     ON_WM_LBUTTONUP()
  1976.       ON_WM_LBUTTONDOWN()
  1977.     ON_WM_MOUSEMOVE()
  1978.     //}}AFX_MSG_MAP
  1979. #ifdef XP_WIN32
  1980.     ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
  1981. #endif
  1982. END_MESSAGE_MAP()
  1983.  
  1984. BOOL CDropdownToolbar::PreTranslateMessage(MSG* pMsg)
  1985. {
  1986.     if( m_pToolTip && pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
  1987.     {
  1988. #ifdef XP_WIN32 
  1989.         // This is needed to get around an MFC bug
  1990.         //   where tooltip is disabled after Modal Dialog is called
  1991.         m_pToolTip->Activate(TRUE);
  1992. #endif
  1993.         m_pToolTip->RelayEvent(pMsg);
  1994.     }
  1995.     return CWnd::PreTranslateMessage(pMsg);
  1996. }
  1997.  
  1998. // 
  1999. #ifdef XP_WIN32 
  2000. // This is needed for non-CFrame owners of a CToolTipCtrl
  2001. BOOL CDropdownToolbar::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
  2002. {
  2003.     TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
  2004.     UINT nID =pNMHDR->idFrom;
  2005.     if (pTTT->uFlags & TTF_IDISHWND)
  2006.     {
  2007.         // idFrom is actually the HWND of the tool
  2008.         nID = ::GetDlgCtrlID((HWND)nID);
  2009.         if(nID) {
  2010.             char * pTipText = FEU_GetToolTipText(nID);
  2011.             if( pTipText ){
  2012.                 // Copy string into buffer - limit is 80 characters
  2013.                 // (use even number for foreign characters
  2014.                 strncpy( pTTT->szText, pTipText, 78);
  2015.  
  2016.                 // Just in case tip was longer than 78 characters!
  2017.                 pTTT->szText[79] = '\0';
  2018.                 return(TRUE);
  2019.             }
  2020.         }
  2021.     }
  2022.     return(FALSE);
  2023. }
  2024. #endif
  2025.  
  2026. void CDropdownToolbar::OnMouseMove(UINT nFlags, CPoint cPoint)
  2027. {
  2028.     CWnd::OnMouseMove(nFlags, cPoint);
  2029.  
  2030.     BOOL bStatusSet = FALSE;
  2031.     char * szStatus;
  2032.     POINT pt = {cPoint.x, cPoint.y};
  2033.     
  2034.     if( m_pMWContext && m_nCallerID && m_CallerRect.top != 0 &&
  2035.             ::PtInRect(&m_CallerRect, pt) ){
  2036.         szStatus = szLoadString(m_nCallerID);
  2037.         if( szStatus ){
  2038.             // Display status line help for caller button
  2039.             // First strip tooltip
  2040.             char * pEnter = strchr( szStatus, '\n');
  2041.             if( pEnter ){
  2042.                 *pEnter = '\0';
  2043.             }
  2044.             wfe_Progress(m_pMWContext, szStatus);
  2045.             // We can skip testing toolbar buttons if we are in caller
  2046.             bStatusSet = TRUE;
  2047.         }
  2048.     }
  2049.     
  2050.     // First button rect
  2051.     RECT rect = {0, 0, ED_TB_BUTTON_WIDTH - 1, 
  2052.                  ED_TB_BUTTON_HEIGHT - 1};
  2053.  
  2054.     for( UINT i = 0; i < m_nButtonCount; i++ ){
  2055.  
  2056.         BOOL bInButton = ::PtInRect(&rect, pt);
  2057.  
  2058.         // Display status line help if within the toolbar
  2059.         if( m_pMWContext && bInButton && !bStatusSet ){
  2060.             szStatus = szLoadString(m_pData[i].nCommandID);
  2061.             if( szStatus ){
  2062.                 //  WACKY FEATURE: Look for accelerator, eg. (Ctrl+x) 
  2063.                 //    in Tooltip portion after a '\n' and move it to 
  2064.                 //    show in case tooltip isn't showing
  2065.                 //    (like when mouse button is down)
  2066.                 char * pEnter = strchr( szStatus, '\n');
  2067.                 if( pEnter ){
  2068.                     char * pParen = strchr( pEnter, '(');
  2069.                     if( pParen ){
  2070.                         *pEnter = ' ';
  2071.                         strcpy(pEnter+1, pParen);
  2072.                     } else {
  2073.                         // No accerlerator, cut off tooltip
  2074.                         *pEnter = '\0';
  2075.                     }
  2076.                 }
  2077.                 wfe_Progress(m_pMWContext, szStatus );
  2078.             } else {
  2079.                 // If string is missing, a blank would be less 
  2080.                 //  confusing then restoring the previous string!
  2081.                 wfe_Progress(m_pMWContext, " ");
  2082.             }
  2083.         }
  2084.  
  2085.         // Set focus to any button if we move over it
  2086.         //  and set button as selected if left mouse button is down
  2087.         if( bInButton ){
  2088.             if( (nFlags & MK_LBUTTON ) && !m_pData[i].pButton->m_bSelected ){
  2089.                 m_pData[i].pButton->SetState(TRUE);
  2090.             }
  2091.             if( !m_pData[i].pButton->m_bFocus ){
  2092.                 m_pData[i].pButton->SetFocus();
  2093.             }
  2094.             break;
  2095.         }
  2096.         // Note: We are outside of current button
  2097.         // Unselect button we moved off of except if its in "pushdown"
  2098.         if( !m_pData[i].pButton->m_bDown &&
  2099.                 m_pData[i].pButton->m_bSelected ) {
  2100.             m_pData[i].pButton->SetState(FALSE);
  2101.             break;
  2102.         }
  2103.         // Next button
  2104.         rect.top += ED_TB_BUTTON_HEIGHT;
  2105.         rect.bottom += ED_TB_BUTTON_HEIGHT;
  2106.     }
  2107. }
  2108.  
  2109. void CDropdownToolbar::OnLButtonDown(UINT nFlags, CPoint cPoint)
  2110. {
  2111.     // Find the button pressed and redraw
  2112.     CRect rect(0, 0, ED_TB_BUTTON_WIDTH - 1, 
  2113.                ED_TB_BUTTON_HEIGHT - 1);
  2114.     
  2115.     POINT pt = {cPoint.x, cPoint.y};
  2116.     for( UINT i = 0; i < m_nButtonCount; i++ ){
  2117.         if( rect.PtInRect(pt) ){
  2118.             // Mark button as pressed and has focus
  2119.             m_pData[i].pButton->SetState(TRUE);
  2120.             m_pData[i].pButton->SetFocus();
  2121.             m_pData[i].pButton->Invalidate();
  2122.             break;
  2123.         }
  2124.         rect.top += ED_TB_BUTTON_HEIGHT;
  2125.         rect.bottom += ED_TB_BUTTON_HEIGHT;
  2126.     }
  2127.     CWnd::OnLButtonDown(nFlags, cPoint);
  2128. }
  2129.  
  2130. // First button up will always destroy toolbar
  2131. //   if not in caller button or a toolbar button
  2132. void CDropdownToolbar::OnLButtonUp(UINT nFlags, CPoint cPoint)
  2133. {
  2134.     POINT pt = {cPoint.x, cPoint.y};
  2135.     BOOL  bExit = FALSE;
  2136.     
  2137.     if( m_CallerRect.top != 0 ){
  2138.         // Don't destroy toolbar if button came up within the
  2139.         //  caller's  button - this allows tooltips to show up
  2140.         //  when mouse moves over button when not held down
  2141.         // REMOVE THIS FOR TOOLBAR DURING MOUSE-DOWN ONLY
  2142.         if( ::PtInRect(&m_CallerRect, pt) ){
  2143.             // Ignore the first time button comes up
  2144.             //   so a simple up+down click doesn't close toolbar
  2145.             if( m_bFirstButtonUp ){
  2146.                 CWnd::OnLButtonUp(nFlags, cPoint);
  2147.                 m_bFirstButtonUp = FALSE;
  2148.                 return;
  2149.             }
  2150.             // Any other time, just exit
  2151.             bExit = TRUE;
  2152.         }
  2153.     }
  2154.  
  2155.     if( !bExit ){
  2156.         // Do Hittest for all buttons
  2157.         CRect rect(0, 0, ED_TB_BUTTON_WIDTH - 1, 
  2158.                    ED_TB_BUTTON_HEIGHT - 1);
  2159.  
  2160.         for( UINT i = 0; i < m_nButtonCount; i++ ){
  2161.             if( rect.PtInRect(pt) ){
  2162.                 // Post message to parent to do what we're supposed to do
  2163.                 //   only if different from initial state (for pushbutton style)
  2164.                 if( m_pParent && m_pData[i].nCommandID != m_nInitialID ){
  2165.                     m_pParent->PostMessage(WM_COMMAND, m_pData[i].nCommandID);
  2166.                 }
  2167.                 break;
  2168.             }
  2169.             rect.top += ED_TB_BUTTON_HEIGHT;
  2170.             rect.bottom += ED_TB_BUTTON_HEIGHT;
  2171.         }
  2172.     }
  2173.  
  2174.     // Restore previous status message
  2175.     if( m_pMWContext ){
  2176.         wfe_Progress(m_pMWContext, "");
  2177.     }
  2178.     DestroyWindow();
  2179. }
  2180.  
  2181.  
  2182. /////////////////////////////////////////////////////////////////////////////
  2183. // CTagDlg dialog - The Arbitrary tag editor
  2184.  
  2185.  
  2186. CTagDlg::CTagDlg(CWnd* pParent, 
  2187.                  MWContext* pMWContext,         // MUST be supplied!
  2188.                  char *pTagData )
  2189.     : CDialog(CTagDlg::IDD, pParent),
  2190.       m_pMWContext(pMWContext),
  2191.       m_bInsert(0),
  2192.       m_bValidTag(0)
  2193. {
  2194.     //{{AFX_DATA_INIT(CTagDlg)
  2195.     m_csTagData = pTagData;
  2196.     //}}AFX_DATA_INIT
  2197.     wfe_GetLayoutViewSize(pMWContext, &m_iFullWidth, &m_iFullHeight);
  2198. }
  2199.  
  2200.  
  2201. void CTagDlg::DoDataExchange(CDataExchange* pDX)
  2202. {
  2203.     CDialog::DoDataExchange(pDX);
  2204.     //{{AFX_DATA_MAP(CTagDlg)
  2205.     DDX_Text(pDX, IDC_EDIT_TAG, m_csTagData);
  2206.     //}}AFX_DATA_MAP
  2207. }
  2208.  
  2209.  
  2210. BEGIN_MESSAGE_MAP(CTagDlg, CDialog)
  2211.     //{{AFX_MSG_MAP(CTagDlg)
  2212.     ON_BN_CLICKED(ID_HELP, OnHelp)
  2213.     ON_BN_CLICKED(IDC_VERIFY_HTML, OnVerifyHtml)
  2214.     //}}AFX_MSG_MAP
  2215. #ifdef XP_WIN32
  2216.     ON_WM_HELPINFO()
  2217. #endif //XP_WIN32
  2218. END_MESSAGE_MAP()
  2219.  
  2220. /////////////////////////////////////////////////////////////////////////////
  2221. // CTagDlg message handlers
  2222.  
  2223. #ifdef XP_WIN32
  2224. BOOL CTagDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
  2225. {
  2226.     OnHelp();
  2227.     return TRUE;
  2228. }
  2229. #endif//XP_WIN32
  2230.  
  2231.  
  2232.  
  2233. BOOL CTagDlg::OnInitDialog() 
  2234. {
  2235.     // Switch back to NETSCAPE.EXE for resource hInstance
  2236.     m_ResourceSwitcher.Reset();
  2237.  
  2238.     if( ED_ELEMENT_UNKNOWN_TAG == EDT_GetCurrentElementType(m_pMWContext) ) {
  2239.         m_csTagData = EDT_GetUnknownTagData(m_pMWContext);
  2240.     } else {
  2241.         m_bInsert = TRUE;
  2242.     }
  2243.  
  2244.     CDialog::OnInitDialog();
  2245.       return TRUE;  // return TRUE unless you set the focus to a control
  2246.                   // EXCEPTION: OCX Property Pages should return FALSE
  2247. }
  2248.  
  2249. Bool CTagDlg::DoVerifyTag( char* pTagString ){
  2250.     ED_TagValidateResult e = EDT_ValidateTag((char*)LPCSTR(m_csTagData), FALSE );
  2251.     UINT nIDS = 0;
  2252.     switch( e ){
  2253.         case ED_TAG_OK:
  2254.             return TRUE;
  2255.         case ED_TAG_UNOPENED:
  2256.             nIDS = IDS_TAG_UNOPENED;
  2257.             break;
  2258.         case ED_TAG_UNCLOSED:
  2259.             nIDS = IDS_TAG_UNCLOSED;
  2260.             break;
  2261.         case ED_TAG_UNTERMINATED_STRING:
  2262.             nIDS = IDS_TAG_UNTERMINATED_STRING;
  2263.             break;
  2264.         case ED_TAG_PREMATURE_CLOSE:
  2265.             nIDS = IDS_TAG_PREMATURE_CLOSE;
  2266.             break;
  2267.         case ED_TAG_TAGNAME_EXPECTED:
  2268.             nIDS = IDS_TAG_TAGNAME_EXPECTED;
  2269.             break;
  2270.         default:
  2271.             nIDS = IDS_TAG_ERROR;
  2272.     }
  2273.  
  2274.     MessageBox( szLoadString(nIDS), 
  2275.                 szLoadString(IDS_ERROR_HTML_CAPTION),
  2276.                 MB_OK | MB_ICONEXCLAMATION);
  2277.     return FALSE;
  2278. }
  2279.  
  2280.  
  2281. void CTagDlg::OnHelp() 
  2282. {
  2283.     NetHelp(HELP_HTML_TAG);
  2284. }
  2285.  
  2286. void CTagDlg::OnOK() 
  2287. {
  2288.     UpdateData(TRUE);
  2289.     if( !DoVerifyTag( (char*)LPCSTR(m_csTagData) ) ){
  2290.         return;
  2291.     }
  2292.  
  2293.     EDT_BeginBatchChanges(m_pMWContext);
  2294.     CDialog::OnOK();
  2295.     
  2296.     if( m_bInsert ){
  2297.         EDT_InsertUnknownTag(m_pMWContext,(char*)LPCSTR(m_csTagData));
  2298.     } else {
  2299.         EDT_SetUnknownTagData(m_pMWContext, (char*)LPCSTR(m_csTagData));
  2300.     }
  2301.     EDT_EndBatchChanges(m_pMWContext);
  2302.  
  2303.     //Note: For Attributes-only editing(e.g., HREF JavaScript),
  2304.     //      caller must get data from m_csTagData;
  2305. }
  2306.  
  2307. void CTagDlg::OnVerifyHtml() 
  2308. {
  2309.     UpdateData(TRUE);
  2310.     DoVerifyTag((char*)LPCSTR(m_csTagData));
  2311. }
  2312.  
  2313. /////////////////////////////////////////////////////////////////////////////
  2314. // CHRuleDlg dialog    Horizontal rule properties in single modal dialog
  2315.  
  2316.  
  2317. CHRuleDlg::CHRuleDlg(CWnd* pParent, 
  2318.               MWContext* pMWContext,         // MUST be supplied!
  2319.               EDT_HorizRuleData* pData )
  2320.     : CDialog(CHRuleDlg::IDD, pParent),
  2321.       m_pMWContext(pMWContext)
  2322. {
  2323.     ASSERT(pMWContext);
  2324.  
  2325.     if (pData){
  2326.         m_pData = pData;
  2327.         m_bInsert = FALSE;
  2328.     } else {
  2329.         m_pData = EDT_NewHorizRuleData();
  2330.         m_bInsert = TRUE;
  2331.     }
  2332.  
  2333.     //{{AFX_DATA_INIT(CHRuleDlg)
  2334.     m_nAlign = 1;
  2335.     m_bShading = TRUE;
  2336.     m_iWidth = 0;
  2337.     m_iHeight = 0;
  2338.     m_iWidthType = 0;
  2339.     //}}AFX_DATA_INIT
  2340.  
  2341.     wfe_GetLayoutViewSize(pMWContext, &m_iFullWidth, NULL);
  2342. }
  2343.  
  2344.  
  2345. void CHRuleDlg::DoDataExchange(CDataExchange* pDX)
  2346. {
  2347.     CDialog::DoDataExchange(pDX);
  2348.     //{{AFX_DATA_MAP(CHRuleDlg)
  2349.     DDX_Radio(pDX, IDC_HR_ALIGN_LEFT, m_nAlign);
  2350.     DDX_Check(pDX, IDC_HR_SHADOW, m_bShading);
  2351.     DDX_Check(pDX, IDC_HR_SAVE_DEFAULT, bSaveDefaultHRule);
  2352.     DDX_CBIndex(pDX, IDC_HR_WIDTH_TYPE, m_iWidthType);
  2353.     DDX_Text(pDX, IDC_HR_HEIGHT, m_iHeight);
  2354.     DDV_MinMaxInt(pDX, m_iHeight, 1, 10000);
  2355.     //}}AFX_DATA_MAP
  2356. }
  2357.  
  2358.  
  2359. BEGIN_MESSAGE_MAP(CHRuleDlg, CDialog)
  2360.     //{{AFX_MSG_MAP(CHRuleDlg)
  2361.     ON_BN_CLICKED(ID_HELP, OnHelp)
  2362.     ON_BN_CLICKED(IDC_EXTRA_HTML, OnExtraHTML)
  2363.     //}}AFX_MSG_MAP
  2364. #ifdef XP_WIN32
  2365.     ON_WM_HELPINFO()
  2366. #endif //XP_WIN32
  2367. END_MESSAGE_MAP()
  2368.  
  2369.  
  2370. void CHRuleDlg::OnExtraHTML()
  2371. {
  2372.     CExtraHTMLDlg dlg(this, &m_pData->pExtra, IDS_HRULE_TAG);
  2373.     dlg.DoModal();
  2374. }
  2375.  
  2376. BOOL ValidateWidth(CDialog* pDlg, int* iWidth, int iWidthType)
  2377. {
  2378.     char szMessage[256];
  2379.     CEdit* pWidthControl = (CEdit*)(pDlg->GetDlgItem(IDC_HR_WIDTH));
  2380.     ASSERT (pWidthControl);
  2381.     char szWidth[16] = "";
  2382.     char *szEndWidth;
  2383.     pWidthControl->GetWindowText(szWidth, 15);
  2384.     
  2385.     int width = (int)strtol( szWidth, &szEndWidth, 10 );
  2386.  
  2387.     int iMaxWidth = (iWidthType == 0) ? 100 : 10000;
  2388.     
  2389.     if( (width < 1  || width > iMaxWidth) || *szEndWidth != '\0'){
  2390.  
  2391.         // Construct a string showing correct range
  2392.         wsprintf( szMessage, szLoadString(IDS_INTEGER_RANGE_ERROR), 1, iMaxWidth );
  2393.  
  2394.         // Notify user with similar message to the DDV_ validation system
  2395.         pDlg->MessageBox(szMessage, szLoadString(AFX_IDS_APP_TITLE), MB_ICONEXCLAMATION | MB_OK);
  2396.         
  2397.         // Put focus in the offending control
  2398.         // And select all text, just like DDV functions
  2399.         pWidthControl->SetFocus();
  2400.         pWidthControl->SetSel(0, -1, TRUE);
  2401.         return FALSE;
  2402.     }
  2403.     // Save values if they are good
  2404.     if( width > 0 ){
  2405.         *iWidth = width;
  2406.     }
  2407.     return TRUE;
  2408. }
  2409.  
  2410. void UpdateWidth(CDialog* pPage, int iWidth)
  2411. {
  2412.     char szBuf[16];
  2413.     wsprintf(szBuf, "%d", iWidth);
  2414.     pPage->GetDlgItem(IDC_HR_WIDTH)->SetWindowText(szBuf);
  2415. }
  2416.  
  2417. /////////////////////////////////////////////////////////////////////////////
  2418. // CHRuleDlg message handlers
  2419.  
  2420. BOOL CHRuleDlg::OnInitDialog() 
  2421. {
  2422.     if ( m_pMWContext == NULL ||
  2423.          m_pData == NULL ) {
  2424.         // Must have data and context!
  2425.         EndDialog(IDCANCEL);
  2426.     }
  2427.     
  2428.     // Switch back to NETSCAPE.EXE for resource hInstance
  2429.     m_ResourceSwitcher.Reset();
  2430.  
  2431.     switch (m_pData->align) {
  2432.         case ED_ALIGN_LEFT:
  2433.             m_nAlign = 0;
  2434.             break;
  2435.         case ED_ALIGN_RIGHT:
  2436.             m_nAlign = 2;
  2437.             break;
  2438.         default:
  2439.             // Default is ED_ALIGN_CENTER
  2440.             m_nAlign = 1;
  2441.             break;
  2442.     }
  2443.     m_iWidth = CASTINT(m_pData->iWidth);
  2444.     m_iWidthType =  m_pData->bWidthPercent ? 0 : 1;
  2445.     m_iHeight = CASTINT(m_pData->size);
  2446.  
  2447.     // NoShading is HTML tag,
  2448.     //  but its better to show positive attributes,
  2449.     //  so we use "3-D Shading", with default = TRUE
  2450.     m_bShading = !m_pData->bNoShade;
  2451.  
  2452.     CComboBox * pCombo = (CComboBox*)GetDlgItem(IDC_HR_WIDTH_TYPE);
  2453.     ASSERT(pCombo);
  2454.     pCombo->AddString(szLoadString(IDS_PERCENT_WINDOW));
  2455.     pCombo->AddString(szLoadString(IDS_PIXELS));
  2456.  
  2457.     // Set caption to indicate a new inserted object
  2458.     if ( m_bInsert ){
  2459.         SetWindowText( szLoadString(IDS_INSERT_HRULE) );
  2460.     }
  2461.  
  2462.     UpdateWidth(this, m_iWidth);
  2463.       CDialog::OnInitDialog();
  2464.     return TRUE;  // return TRUE unless you set the focus to a control
  2465.                   // EXCEPTION: OCX Property Pages should return FALSE
  2466. }
  2467.  
  2468. void CHRuleDlg::OnHelp() 
  2469. {
  2470.     NetHelp(HELP_PROPS_HRULE);
  2471. }
  2472.  
  2473.  
  2474.  
  2475. #ifdef XP_WIN32
  2476. BOOL CHRuleDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
  2477. {
  2478.     OnHelp();
  2479.     return TRUE;
  2480. }
  2481. #endif//XP_WIN32
  2482.  
  2483.  
  2484.  
  2485. void CHRuleDlg::OnOK() 
  2486. {
  2487.     if( !UpdateData(TRUE) ||
  2488.         !ValidateWidth(this, &m_iWidth, m_iWidthType ) ){
  2489.         return;
  2490.     }
  2491.  
  2492.     EDT_BeginBatchChanges(m_pMWContext);
  2493.     switch (m_nAlign) {
  2494.         case 0:
  2495.             m_pData->align = ED_ALIGN_LEFT;
  2496.             break;
  2497.         case 1:
  2498.             m_pData->align = ED_ALIGN_CENTER;
  2499.             break;
  2500.         case 2:
  2501.             m_pData->align = ED_ALIGN_RIGHT;
  2502.             break;
  2503.     }
  2504.     m_pData->iWidth = m_iWidth;
  2505.     m_pData->bWidthPercent = (m_iWidthType == 0);
  2506.     m_pData->size = m_iHeight;
  2507.     m_pData->bNoShade = !m_bShading;
  2508.  
  2509.     if ( m_bInsert ) {
  2510.         EDT_InsertHorizRule( m_pMWContext, m_pData );
  2511.     } else {
  2512.         EDT_SetHorizRuleData( m_pMWContext, m_pData );
  2513.     }
  2514.     EDT_EndBatchChanges(m_pMWContext);
  2515.  
  2516.     if( bSaveDefaultHRule ){
  2517.         // Save current values as default preferences
  2518.         PREF_SetIntPref("editor.hrule.height",m_iHeight);
  2519.         PREF_SetIntPref("editor.hrule.width",m_iWidth);
  2520.         if( m_iWidthType == 0 ){
  2521.             PREF_SetBoolPref("editor.hrule.width_percent",TRUE);
  2522.         } else {
  2523.             PREF_SetBoolPref("editor.hrule.width_percent",FALSE);
  2524.         }
  2525.         if( m_bShading ){
  2526.             PREF_SetBoolPref("editor.hrule.shading",TRUE);
  2527.         } else {
  2528.             PREF_SetBoolPref("editor.hrule.shading",FALSE);
  2529.         }
  2530.         PREF_SetIntPref("editor.hrule.align",m_pData->align);
  2531.     }
  2532.     CDialog::OnOK();
  2533. }
  2534.  
  2535. BOOL CHRuleDlg::DestroyWindow() 
  2536. {
  2537.     if (m_pData) {
  2538.         EDT_FreeHorizRuleData(m_pData);
  2539.     }
  2540.     return CDialog::DestroyWindow();
  2541. }
  2542. /////////////////////////////////////////////////////////////////////////////
  2543. // CTargetDlg dialog    Set Target(named anchor) properties in single modal dialog
  2544.  
  2545.  
  2546. CTargetDlg::CTargetDlg(CWnd* pParent,
  2547.                        MWContext* pMWContext,       // MUST be supplied!
  2548.                        char *pName)                 // Existing target
  2549.     : CDialog(CTargetDlg::IDD, pParent),
  2550.       m_pMWContext(pMWContext),
  2551.       m_bInsert(0)
  2552. {
  2553.     ASSERT(pMWContext);
  2554.     //{{AFX_DATA_INIT(CTargetDlg)
  2555.     m_csName = pName;
  2556.     //}}AFX_DATA_INIT
  2557. }
  2558.  
  2559.  
  2560. void CTargetDlg::DoDataExchange(CDataExchange* pDX)
  2561. {
  2562.     CDialog::DoDataExchange(pDX);
  2563.     //{{AFX_DATA_MAP(CTargetDlg)
  2564.     DDX_Text(pDX, IDC_TARGET_NAME, m_csName);
  2565.     //}}AFX_DATA_MAP
  2566. }
  2567.  
  2568.  
  2569. BEGIN_MESSAGE_MAP(CTargetDlg, CDialog)
  2570.     //{{AFX_MSG_MAP(CTargetDlg)
  2571.     ON_EN_CHANGE(IDC_TARGET_NAME, OnChangeTargetName)
  2572.     ON_BN_CLICKED(ID_HELP, OnHelp)
  2573.     //}}AFX_MSG_MAP
  2574. #ifdef XP_WIN32
  2575.     ON_WM_HELPINFO()
  2576. #endif //XP_WIN32
  2577. END_MESSAGE_MAP()
  2578.  
  2579. // CTargetDlg message handlers
  2580.  
  2581. BOOL CTargetDlg::OnInitDialog() 
  2582. {
  2583.     // Switch back to NETSCAPE.EXE for resource hInstance
  2584.     m_ResourceSwitcher.Reset();
  2585.  
  2586.     if( ED_ELEMENT_TARGET == EDT_GetCurrentElementType(m_pMWContext) ) {
  2587.         m_csName = EDT_GetTargetData(m_pMWContext);
  2588.     } else {
  2589.         m_bInsert = TRUE;
  2590.         // Use current selected text as suggested target name...
  2591.         char *pName =  (char*)LO_GetSelectionText(ABSTRACTCX(m_pMWContext)->GetDocumentContext());
  2592.         if ( pName ){
  2593.             char *pTemp = pName;
  2594.             char *pEnd = pName + min( XP_STRLEN(pName), 50);
  2595.             // Skip over leading white-space
  2596.             while( XP_IS_SPACE(*pTemp) && pTemp < pEnd ) pTemp++;
  2597.             if( pTemp < pEnd ){
  2598.                 char *pStart = pTemp;
  2599.                 // Stop at any CR/LF and replace
  2600.                 //  other whitespace with real spaces (OR UNDERSCORE?)
  2601.                 while( pTemp <= pEnd ){
  2602.                     if( *pTemp == '\n' || *pTemp == '\r' ){
  2603.                         // Stop at end of line
  2604.                         pEnd = pTemp;
  2605.                         break;
  2606.                     }
  2607.                     if( XP_IS_SPACE(*pTemp) ) *pTemp = ' ';
  2608.                     pTemp++;
  2609.                 }
  2610.                 pTemp = pEnd;
  2611.                 // Find last character before the last space from the end
  2612.                 while( !XP_IS_SPACE(*pTemp) && pTemp != pName ) pTemp--;
  2613.                 if( pTemp != pName ) *pTemp = '\0';
  2614.                 m_csName = pStart;
  2615.                 m_csName.TrimRight();
  2616.             }
  2617.             XP_FREE(pName);
  2618.         }
  2619.     }
  2620.  
  2621.     // Get the list of existing targets to
  2622.     //  warn if target name is already used
  2623.     m_pTargetList = EDT_GetAllDocumentTargets(m_pMWContext);
  2624.  
  2625.     CDialog::OnInitDialog();
  2626.  
  2627.     return TRUE;  // return TRUE unless you set the focus to a control
  2628.                   // EXCEPTION: OCX Property Pages should return FALSE
  2629. }
  2630.  
  2631. void CTargetDlg::OnHelp() 
  2632. {
  2633.     NetHelp(HELP_PROPS_TARGET);
  2634. }
  2635.  
  2636.  
  2637.  
  2638. #ifdef XP_WIN32
  2639. BOOL CTargetDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
  2640. {
  2641.     OnHelp();
  2642.     return TRUE;
  2643. }
  2644. #endif//XP_WIN32
  2645.  
  2646.  
  2647.  
  2648. void CTargetDlg::OnOK() 
  2649. {
  2650.     EDT_BeginBatchChanges(m_pMWContext);
  2651.  
  2652.     CDialog::OnOK();
  2653.     // Remove trailing spaces and quote marks
  2654.     CleanupString(m_csName);
  2655.  
  2656.     // Strip off hash mark
  2657.     if(!m_csName.IsEmpty() && m_csName.GetAt(0) == '#'){
  2658.         m_csName = m_csName.Mid(1);;
  2659.     }    
  2660.     if( !m_csName.IsEmpty() ){
  2661.         if( m_bInsert ){
  2662.             EDT_InsertTarget(m_pMWContext, (char*)LPCSTR(m_csName));
  2663.         } else {
  2664.             EDT_SetTargetData(m_pMWContext, (char*)LPCSTR(m_csName));
  2665.         }
  2666.     }
  2667.  
  2668.     EDT_EndBatchChanges(m_pMWContext);
  2669. }
  2670.  
  2671. void CTargetDlg::OnChangeTargetName()
  2672. {
  2673.     UpdateData(TRUE);
  2674.     // Remove trailing spaces and quote marks, but
  2675.     // use temp string to cleanup and don't send string back with UpdateData
  2676.     // This upsets caret location etc.
  2677.     CString csTemp = m_csName;
  2678.     CleanupString(csTemp);
  2679.     GetDlgItem(IDOK)->EnableWindow(!csTemp.IsEmpty());
  2680. }
  2681.  
  2682. ////////////////////////////////////////////////////////////////////////////
  2683. // Special class to control Background color of static control
  2684. //
  2685. // CColorStatic
  2686.  
  2687. CColorStatic::
  2688.     CColorStatic(COLORREF crTextColor,        // Default is black text
  2689.                  COLORREF crBackColor,   // on gray Background
  2690.                  ED_BorderStyle nStyle)
  2691. {
  2692.     m_crTextColor = crTextColor;
  2693.     m_crBackColor = crBackColor;
  2694.     m_nBorderStyle = nStyle;
  2695.  
  2696.     // Create a white brush for the Background
  2697.    m_brush.CreateSolidBrush(crBackColor|0x02000000); // Like PALETTERGB
  2698. }
  2699.  
  2700. CColorStatic::~CColorStatic()
  2701. {
  2702. }
  2703.  
  2704. BEGIN_MESSAGE_MAP(CColorStatic, CStatic)
  2705.     //{{AFX_MSG_MAP(CColorStatic)
  2706.         // NOTE - the ClassWizard will add and remove mapping macros here.
  2707.     //}}AFX_MSG_MAP
  2708. END_MESSAGE_MAP()
  2709.  
  2710. /////////////////////////////////////////////////////////////////////////////
  2711. // CColorStatic message handlers
  2712. BOOL CColorStatic::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
  2713.                                  LRESULT* pLResult)
  2714. {
  2715.    int nCtlType = (int)HIWORD(lParam);
  2716.  
  2717.     // If "message" is not the message you're after, do default processing:
  2718.    if (message != WM_CTLCOLOR)
  2719.    {
  2720.       return CStatic::OnChildNotify(message,wParam,lParam,pLResult);
  2721.    }
  2722.  
  2723.    HDC hdcChild = (HDC)wParam;
  2724.    SetTextColor(hdcChild, m_crTextColor);
  2725.    SetBkColor(hdcChild, m_crTextColor);
  2726.  
  2727.     // Send what would have been the return value of OnCtlColor() - the brush
  2728.     // handle - back in pLResult:
  2729.    *pLResult = (LRESULT)(m_brush.GetSafeHandle());
  2730.  
  2731.     // Return TRUE to indicate that the message was handled:
  2732.    return TRUE;
  2733. }
  2734.  
  2735. #define MAX_META_NAME_LEN   100
  2736. #define MAX_META_VALUE_LEN  400
  2737. enum {
  2738.     EDIT_NONE,
  2739.     EDIT_EQUIV,
  2740.     EDIT_META
  2741. };
  2742. /////////////////////////////////////////////////////////////////////
  2743. // Document Properties Pages
  2744. //
  2745. // First page = general info
  2746. //    "Fixed" Meta Tags we always include
  2747. //
  2748. CDocInfoPage::CDocInfoPage(CWnd* pParent, MWContext * pMWContext,
  2749.                            CEditorResourceSwitcher * pResourceSwitcher,
  2750.                            EDT_PageData * pPageData)
  2751.     : CNetscapePropertyPage(CDocInfoPage::IDD),
  2752.       m_pMWContext(pMWContext),
  2753.       m_pResourceSwitcher(pResourceSwitcher),
  2754.       m_bActivated(0),
  2755.       m_pPageData(pPageData)
  2756. {
  2757.     //{{AFX_DATA_INIT(CDocInfoPage)
  2758.     m_csAuthor = _T("");
  2759.     m_csClassification = _T("");
  2760.     m_csDescription = _T("");
  2761.     m_csTitle = _T("");
  2762.     m_csURL = _T("");
  2763.     m_csKeyWords = _T("");
  2764.     //}}AFX_DATA_INIT
  2765.     ASSERT(pMWContext);
  2766.     ASSERT(pPageData);
  2767.  
  2768. #ifdef XP_WIN32
  2769.     // Set the hInstance so we get template from editor's resource DLL
  2770.     m_psp.hInstance = AfxGetResourceHandle();
  2771. #endif
  2772. }
  2773.  
  2774. ////////////////////////////////////////////////////////////////////////
  2775. BOOL CDocInfoPage::OnSetActive() 
  2776. {
  2777.     if(m_pResourceSwitcher && !m_bActivated){
  2778.         // We must be sure we have switched
  2779.         //  the first time here - before dialog creation
  2780.         m_pResourceSwitcher->switchResources();
  2781.     }
  2782.     if(!CPropertyPage::OnSetActive())
  2783.         return(FALSE);
  2784.  
  2785.     if(m_bActivated)
  2786.         return(TRUE);
  2787.  
  2788.     // Switch back to EXE's resources
  2789.     if( m_pResourceSwitcher ){
  2790.         m_pResourceSwitcher->Reset();
  2791.     }
  2792.  
  2793.     m_bActivated = TRUE;
  2794.     
  2795.     // This should be same as hist_ent->title??
  2796.     m_csTitle = m_pPageData->pTitle;
  2797.  
  2798.     History_entry * hist_ent = SHIST_GetCurrent(&m_pMWContext->hist);
  2799.     if(hist_ent && hist_ent->address) {
  2800.         m_csURL = hist_ent->address;
  2801.         WFE_CondenseURL(m_csURL, 80, FALSE);
  2802.         GetDlgItem(IDC_DOC_URL)->SetWindowText(CHAR_STR(m_csURL));
  2803.  
  2804.         // If empty, fill in title with Filename part of URL without extension
  2805.         if( m_csTitle.IsEmpty() ){
  2806.             char * pTitle = EDT_GetPageTitleFromFilename(hist_ent->address);
  2807.             if( pTitle ){
  2808.                 m_csTitle = pTitle;
  2809.                 XP_FREE(pTitle);
  2810.             }
  2811.         }
  2812.     }
  2813.  
  2814.     
  2815.     // Get data from meta tags:
  2816.     int count = EDT_MetaDataCount(m_pMWContext);
  2817.     for ( int i = 0; i < count; i++ ) {
  2818.         EDT_MetaData* pData = EDT_GetMetaData(m_pMWContext, i);
  2819.         if ( !pData->bHttpEquiv ) {
  2820.             if ( 0 == _stricmp(pData->pName, "Author") ) {
  2821.                 m_csAuthor = pData->pContent;
  2822.             } else if ( 0 == _stricmp(pData->pName, "Classification") ) {
  2823.                 m_csClassification =  pData->pContent;
  2824.             } else if ( 0 == _stricmp(pData->pName, "Description") ) {
  2825.                 m_csDescription = pData->pContent;
  2826.             } else if ( 0 == _stricmp(pData->pName, "KeyWords") ) {
  2827.                 m_csKeyWords =  pData->pContent;
  2828.             }/* else if ( 0 == _stricmp(pData->pName, "Created") ) {
  2829.                 m_csCreateDate = pData->pContent;
  2830.             } else if ( 0 == _stricmp(pData->pName, "Last-Modified") ) {
  2831.                 m_csUpdateDate = pData->pContent;
  2832.             }*/
  2833.         }
  2834.     }
  2835.     if( m_csAuthor.IsEmpty() ){
  2836.         // Get name from preferences if none supplied
  2837.         char * pAuthor = NULL;
  2838.         PREF_CopyCharPref("editor.author", &pAuthor);    
  2839.         m_csAuthor = pAuthor;
  2840.         XP_FREEIF(pAuthor);
  2841.     }
  2842.     UpdateData(FALSE);    
  2843.     return(TRUE);
  2844. }
  2845.  
  2846. // Create a MetaData structure and save it 
  2847. // This commits change - NO BUFFERING
  2848. // Be sure to strip off spaces and quotes before calling this
  2849. void CDocInfoPage::SetMetaData(char * pName, char * pValue)
  2850. {
  2851.     EDT_MetaData *pData = EDT_NewMetaData();
  2852.     if ( pData ) {
  2853.         pData->bHttpEquiv = FALSE;
  2854.         if ( pName && XP_STRLEN(pName) > 0 ) {
  2855.             pData->pName = XP_STRDUP(pName);
  2856.             if ( pValue && XP_STRLEN(pValue) > 0 ) {
  2857.                 pData->pContent = XP_STRDUP(pValue);
  2858.                 EDT_SetMetaData(m_pMWContext, pData);
  2859.             } else {
  2860.                 // (Don't really need to do this)
  2861.                 pData->pContent = NULL; 
  2862.                 // Remove the item            
  2863.                 EDT_DeleteMetaData(m_pMWContext, pData);
  2864.             }
  2865.             OkToClose();
  2866.         }
  2867.         EDT_FreeMetaData(pData);
  2868.     }
  2869. }
  2870.  
  2871. void CDocInfoPage::OnHelp() 
  2872. {
  2873.     NetHelp(HELP_DOC_PROPS_GENERAL);
  2874. }
  2875.  
  2876. void CDocInfoPage::OnOK() 
  2877. {
  2878.     CPropertyPage::OnOK();
  2879.  
  2880.     // never visited this page or no change -- don't bother
  2881.     if(!m_bActivated ||
  2882.        !IS_APPLY_ENABLED(this)){
  2883.         return;
  2884.     }    
  2885.     m_bActivated = TRUE;
  2886.  
  2887.     // EDT_BeginBatchChanges(m_pMWContext);
  2888.  
  2889.     // Replace Title and FontDefURL
  2890.     XP_FREEIF(m_pPageData->pTitle);
  2891.  
  2892.     CleanupString(m_csTitle);
  2893.  
  2894.     if ( !m_csTitle.IsEmpty() ) {
  2895.         m_pPageData->pTitle = XP_STRDUP(m_csTitle);
  2896.     }
  2897.  
  2898.     EDT_SetPageData(m_pMWContext, m_pPageData);
  2899.  
  2900.     // Trim quotes and set data meta tags
  2901.     CleanupString(m_csAuthor);
  2902.     if ( !m_csAuthor.IsEmpty() ) {
  2903.         // Don't wipe out author field if empty?
  2904.         SetMetaData("Author", CHAR_STR(m_csAuthor));
  2905.     }
  2906.  
  2907.     CleanupString(m_csClassification);
  2908.     SetMetaData("Classification", CHAR_STR(m_csClassification));
  2909.  
  2910.     CleanupString(m_csDescription);
  2911.     SetMetaData("Description", CHAR_STR(m_csDescription));
  2912.  
  2913.     CleanupString(m_csKeyWords);
  2914.     SetMetaData("KeyWords", CHAR_STR(m_csKeyWords));
  2915.  
  2916.     // TODO: MAKE THIS STRING IF NEW DOC???
  2917.     // SetMetaData(FALSE, "Created", CHAR_STR());
  2918.     // SetMetaData(FALSE, "Last-Modified", CHAR_STR());
  2919.  
  2920.     OkToClose();
  2921.     //EDT_EndBatchChanges(m_pMWContext);
  2922. }
  2923.  
  2924. void CDocInfoPage::DoDataExchange(CDataExchange* pDX)
  2925. {
  2926.     CPropertyPage::DoDataExchange(pDX);
  2927.     //{{AFX_DATA_MAP(CDocInfoPage)
  2928.     DDX_Text(pDX, IDC_DOC_AUTHOR, m_csAuthor);
  2929.     DDX_Text(pDX, IDC_DOC_CLASIFICATION, m_csClassification);
  2930.     DDX_Text(pDX, IDC_DOC_DESCRIPTION, m_csDescription);
  2931.     DDX_Text(pDX, IDC_DOC_TITLE, m_csTitle);
  2932.     DDX_Text(pDX, IDC_DOC_URL, m_csURL);
  2933.     DDX_Text(pDX, IDC_KEYWORDS, m_csKeyWords);
  2934.     //}}AFX_DATA_MAP
  2935. }
  2936.  
  2937. BEGIN_MESSAGE_MAP(CDocInfoPage, CNetscapePropertyPage)
  2938.     //{{AFX_MSG_MAP(CDocInfoPage)
  2939.     ON_EN_CHANGE(IDC_DOC_AUTHOR, EnableApply)
  2940.     ON_EN_CHANGE(IDC_DOC_CLASIFICATION, EnableApply)
  2941.     ON_EN_CHANGE(IDC_DOC_DESCRIPTION, EnableApply)
  2942.     ON_EN_CHANGE(IDC_DOC_TITLE, EnableApply)
  2943.     ON_EN_CHANGE(IDC_KEYWORDS, EnableApply)
  2944.     //}}AFX_MSG_MAP
  2945. END_MESSAGE_MAP()
  2946.  
  2947.  
  2948. void CDocInfoPage::EnableApply() 
  2949. {
  2950.     SetModified(TRUE);
  2951. }
  2952.  
  2953. /////////////////////////////////////////////////////////////////////////////
  2954. // Local helpers for color params converversions
  2955.  
  2956. // Allocate and initialize a new scheme struct and add it to list
  2957. EDT_ColorSchemeData * AddNewColorData( XP_List *pSchemeData )
  2958. {
  2959.     EDT_ColorSchemeData * pColorData = XP_NEW(EDT_ColorSchemeData);
  2960.  
  2961.     if(!pColorData) {
  2962.         return NULL;
  2963.     }
  2964.     memset(pColorData, 0, sizeof(EDT_ColorSchemeData));
  2965.  
  2966.     XP_ListAddObjectToEnd(pSchemeData, pColorData);
  2967.     return pColorData;
  2968. }
  2969.  
  2970. //////////////////////////////////////////////////////////////////////
  2971. /*
  2972. // For reference: the built-in default colors
  2973. LO_DEFAULT_FG_RED         0
  2974. LO_DEFAULT_FG_GREEN       0
  2975. LO_DEFAULT_FG_BLUE        0
  2976.  
  2977. LO_DEFAULT_BG_RED         192
  2978. LO_DEFAULT_BG_GREEN       192
  2979. LO_DEFAULT_BG_BLUE        192
  2980.  
  2981. LO_UNVISITED_ANCHOR_RED   0
  2982. LO_UNVISITED_ANCHOR_GREEN 0
  2983. LO_UNVISITED_ANCHOR_BLUE  238
  2984.  
  2985. LO_VISITED_ANCHOR_RED     85
  2986. LO_VISITED_ANCHOR_GREEN   26
  2987. LO_VISITED_ANCHOR_BLUE    139
  2988.  
  2989. LO_SELECTED_ANCHOR_RED    255
  2990. LO_SELECTED_ANCHOR_GREEN  0
  2991. LO_SELECTED_ANCHOR_BLUE   0
  2992. // Offsets for getting defaults from lo_master_colors
  2993. // eg:  
  2994.         red = lo_master_colors[LO_COLOR_FG].red;
  2995.         green = lo_master_colors[LO_COLOR_FG].green;
  2996.         blue = lo_master_colors[LO_COLOR_FG].blue;
  2997.  
  2998. LO_COLOR_BG    0
  2999. LO_COLOR_FG    1
  3000. LO_COLOR_LINK    2
  3001. LO_COLOR_VLINK    3
  3002. LO_COLOR_ALINK    4
  3003. */
  3004.  
  3005. /////////////////////////////////////////////////////////////////////
  3006. CDocColorPage::CDocColorPage(CWnd* pParent,
  3007.                              UINT nIDCaption,
  3008.                              UINT nIDFocus,
  3009.                              MWContext * pMWContext,
  3010.                              CEditorResourceSwitcher * pResourceSwitcher,
  3011.                              EDT_PageData * pPageData )
  3012.     : CNetscapePropertyPage(CDocColorPage::IDD, nIDCaption, nIDFocus),
  3013.       m_bActivated(0),
  3014.       m_pMWContext(pMWContext),
  3015.       m_pResourceSwitcher(pResourceSwitcher),
  3016.       m_pPageData(pPageData),
  3017.       m_bImageChanged(0),
  3018.       m_bValidImage(0),
  3019.       m_pSchemeData(0),
  3020.       m_hPal(0)
  3021. {
  3022.     ASSERT(pMWContext);
  3023.  
  3024.     //{{AFX_DATA_INIT(CDocColorPage)
  3025.     m_csBackgroundImage = _T("");
  3026.     m_csSelectedScheme = _T("");
  3027.     m_bNoSave = 0;
  3028.     //}}AFX_DATA_INIT
  3029.  
  3030.     //m_csCustomBackgroundImage = _T("");
  3031.     m_csBrowserBackgroundImage = _T("");
  3032.  
  3033. #ifdef XP_WIN32
  3034.     // Set the hInstance so we get template from editor's resource DLL
  3035.     m_psp.hInstance = AfxGetResourceHandle();
  3036. #endif
  3037. }
  3038.  
  3039. CDocColorPage::~CDocColorPage()
  3040. {
  3041.     // Destroy the scheme list
  3042.     // TODO: Move to XP code
  3043.     if ( m_pSchemeData ) {
  3044.         EDT_ColorSchemeData *pColorData;
  3045.         XP_List * list_ptr = m_pSchemeData;
  3046.         while ((pColorData = (EDT_ColorSchemeData *)XP_ListNextObject(list_ptr))) {
  3047.             if ( pColorData->pSchemeName ) {
  3048.                 XP_FREE( pColorData->pSchemeName );
  3049.             }
  3050.             if ( pColorData->pBackgroundImage ) {
  3051.                 XP_FREE( pColorData->pBackgroundImage );
  3052.             }
  3053.             XP_FREE(pColorData);
  3054.         }
  3055.         XP_ListDestroy(m_pSchemeData);
  3056.     }
  3057. }
  3058.  
  3059. void CDocColorPage::DoDataExchange(CDataExchange* pDX)
  3060. {
  3061.     CPropertyPage::DoDataExchange(pDX);
  3062.     //{{AFX_DATA_MAP(CDocColorPage)
  3063.     DDX_Text(pDX, IDC_BKGRND_IMAGE, m_csBackgroundImage);
  3064.     DDX_CBString(pDX, IDC_SCHEME_LIST, m_csSelectedScheme);
  3065.     DDX_Check(pDX, IDC_NO_SAVE_IMAGE, m_bNoSave);
  3066.     //}}AFX_DATA_MAP
  3067. }
  3068.  
  3069. BEGIN_MESSAGE_MAP(CDocColorPage, CNetscapePropertyPage)
  3070.     //{{AFX_MSG_MAP(CDocColorPage)
  3071.     ON_BN_CLICKED(IDC_BKGRND_USE_IMAGE, OnUseBkgrndImage)
  3072.     ON_BN_CLICKED(IDC_CHOOSE_BACKGROUND, OnChooseBkgrndImage)
  3073.     ON_CBN_SELCHANGE(IDC_SCHEME_LIST, OnSelchangeSchemeList)
  3074.     ON_EN_CHANGE(IDC_BKGRND_IMAGE, OnChangeBkgrndImage)
  3075.     ON_EN_KILLFOCUS(IDC_BKGRND_IMAGE, OnKillfocusBkgrndImage)
  3076.     ON_WM_PAINT()
  3077.     ON_BN_CLICKED(IDC_CHOOSE_TEXT_COLOR, OnChooseTextColor)
  3078.     ON_BN_CLICKED(IDC_CHOOSE_LINK_COLOR, OnChooseLinkColor)
  3079.     ON_BN_CLICKED(IDC_CHOOSE_ACTIVELINK_COLOR, OnChooseActivelinkColor)
  3080.     ON_BN_CLICKED(IDC_CHOOSE_FOLLOWEDLINK_COLOR, OnChooseFollowedlinkColor)
  3081.     ON_BN_CLICKED(IDC_CHOOSE_BKGRND_COLOR, OnChooseBkgrndColor)
  3082.     ON_BN_CLICKED(IDC_SET_DOC_COLORS, OnColorsRadioButtons)
  3083.     ON_BN_CLICKED(IDC_USE_BROWSER_COLORS, OnColorsRadioButtons)
  3084.     ON_BN_CLICKED(IDC_USE_AS_DEFAULT, OnUseAsDefault)
  3085.     ON_BN_CLICKED(IDC_NO_SAVE_IMAGE, OnNoSave)
  3086.     //}}AFX_MSG_MAP
  3087. END_MESSAGE_MAP()
  3088.  
  3089. #include "timer.h"  //For nettimer.OnIdle()
  3090.  
  3091. BOOL CDocColorPage::OnSetActive() 
  3092. {
  3093.     if(m_pResourceSwitcher && !m_bActivated){
  3094.         // We must be sure we have switched
  3095.         //  the first time here - before dialog creation
  3096.         m_pResourceSwitcher->switchResources();
  3097.     }
  3098.  
  3099.     if(!CPropertyPage::OnSetActive())
  3100.         return(FALSE);
  3101.  
  3102.     if(m_bActivated)
  3103.         return(TRUE);
  3104.  
  3105.     // Switch back to EXE's resources
  3106.     if( m_pResourceSwitcher ){
  3107.         m_pResourceSwitcher->Reset();
  3108.     }
  3109.  
  3110.     m_hPal = WFE_GetUIPalette(GetParentFrame());
  3111.  
  3112.     if( !m_TextColorButton.Subclass(this, IDC_CHOOSE_TEXT_COLOR, &m_crText) ||
  3113.         !m_LinkColorButton.Subclass(this, IDC_CHOOSE_LINK_COLOR, &m_crLink) ||
  3114.         !m_ActiveLinkColorButton.Subclass(this, IDC_CHOOSE_ACTIVELINK_COLOR, &m_crActiveLink) ||
  3115.         !m_FollowedLinkColorButton.Subclass(this, IDC_CHOOSE_FOLLOWEDLINK_COLOR, &m_crFollowedLink) || 
  3116.         !m_BackgroundColorButton.Subclass(this, IDC_CHOOSE_BKGRND_COLOR, &m_crBackground) ){
  3117.         return FALSE;
  3118.     }
  3119.  
  3120.     // TODO - do stuff here
  3121.     m_bActivated = TRUE;
  3122.     
  3123.     CComboBox * pSchemeListBox = (CComboBox*)GetDlgItem(IDC_SCHEME_LIST);
  3124.  
  3125.     CFont fontPreview;
  3126.     //  Create a font for the preview window
  3127.     if( GetSystemMetrics(SM_DBCSENABLED) ){
  3128.         HFONT    hFont = NULL;
  3129.  
  3130. #ifdef _WIN32
  3131.         hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  3132. #endif
  3133.  
  3134.         if (!hFont){
  3135.             hFont = (HFONT)GetStockObject(SYSTEM_FONT);
  3136.         }
  3137.         fontPreview.Attach(hFont);
  3138.         GetDlgItem(IDC_DOC_COLOR_PREVIEW)->SetFont(&fontPreview);
  3139.     } else {
  3140.           //  Get a 1-pixel font
  3141.         LOGFONT logFont;
  3142.         memset(&logFont, 0, sizeof(logFont));
  3143.         logFont.lfHeight = -18; // about 14 points?
  3144.         logFont.lfWeight = FW_BOLD;
  3145.         logFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
  3146.         lstrcpy(logFont.lfFaceName,"MS Serif");
  3147.  
  3148.         if( fontPreview.CreateFontIndirect(&logFont) ){
  3149.             GetDlgItem(IDC_DOC_COLOR_PREVIEW)->SetFont(&fontPreview);
  3150.         } else {
  3151.             TRACE0("Could Not create preview for Color Dialog\n");
  3152.         }
  3153.     }
  3154.  
  3155.     // Get current stuff from preferences
  3156.     char * prefStr = NULL;
  3157.     PREF_CopyCharPref("editor.color_scheme",&prefStr);
  3158.     if (prefStr) {
  3159.         m_csSelectedScheme = prefStr;
  3160.         XP_FREE(prefStr);
  3161.     } else m_csSelectedScheme = "";
  3162.  
  3163.     // Construct a list of Schemes
  3164.     // TODO: Make this a global list and move to XP code
  3165.     m_pSchemeData = XP_ListNew();
  3166.  
  3167.     EDT_ColorSchemeData * pColorData = AddNewColorData( m_pSchemeData );
  3168.     if ( pColorData ) {
  3169.         // First scheme is always the Netscape Default Colors
  3170.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_COLOR_SCHEME_NS_DEFAULT));
  3171.         
  3172.         COLORREF clr;        
  3173.         PREF_GetColorPrefDWord("editor.text_color",&clr);
  3174.         WFE_SetLO_Color( clr, &pColorData->ColorText );
  3175.  
  3176.         PREF_GetColorPrefDWord("editor.link_color",&clr);
  3177.         WFE_SetLO_Color( clr, &pColorData->ColorLink );
  3178.  
  3179.         PREF_GetColorPrefDWord("editor.active_link_color",&clr);
  3180.         WFE_SetLO_Color( clr, &pColorData->ColorActiveLink );
  3181.  
  3182.         PREF_GetColorPrefDWord("editor.followed_link_color",&clr);
  3183.         WFE_SetLO_Color( clr, &pColorData->ColorFollowedLink );
  3184.         
  3185.         PREF_GetColorPrefDWord("editor.background_color",&clr);
  3186.         WFE_SetLO_Color( clr, &pColorData->ColorBackground );
  3187.         // Add name to listbox
  3188.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3189.     }
  3190.  
  3191.     pColorData = AddNewColorData( m_pSchemeData );
  3192.     if ( pColorData ) {
  3193.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_WHITE));
  3194.         WFE_SetLO_Color( RGB(0,0,0), 
  3195.                          &pColorData->ColorText );
  3196.         WFE_SetLO_Color( RGB(255,255,255),
  3197.                          &pColorData->ColorBackground );
  3198.         WFE_SetLO_Color( RGB(255,0,0),
  3199.                          &pColorData->ColorLink );
  3200.         WFE_SetLO_Color( RGB(128,0,128),
  3201.                          &pColorData->ColorFollowedLink );
  3202.         WFE_SetLO_Color( RGB(0,0,255),
  3203.                          &pColorData->ColorActiveLink );
  3204.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3205.     }
  3206.  
  3207.     pColorData = AddNewColorData( m_pSchemeData );
  3208.     if ( pColorData ) {
  3209.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_OFFWHITE));
  3210.         WFE_SetLO_Color( RGB(0,0,0), 
  3211.                          &pColorData->ColorText );
  3212.         WFE_SetLO_Color( RGB(255,240,240),
  3213.                          &pColorData->ColorBackground );
  3214.         WFE_SetLO_Color( RGB(255,0,0),
  3215.                          &pColorData->ColorLink );
  3216.         WFE_SetLO_Color( RGB(128,0,128),
  3217.                          &pColorData->ColorFollowedLink );
  3218.         WFE_SetLO_Color( RGB(0,0,255),
  3219.                          &pColorData->ColorActiveLink );
  3220.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3221.     }
  3222.  
  3223.     pColorData = AddNewColorData( m_pSchemeData );
  3224.     if ( pColorData ) {
  3225.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_LTYELLOW));
  3226.         WFE_SetLO_Color( RGB(0,0,0), 
  3227.                          &pColorData->ColorText );
  3228.         WFE_SetLO_Color( RGB(255,255,192),
  3229.                          &pColorData->ColorBackground );
  3230.         WFE_SetLO_Color( RGB(0,0,255),
  3231.                          &pColorData->ColorLink );
  3232.         WFE_SetLO_Color( RGB(128,0,128),
  3233.                          &pColorData->ColorFollowedLink );
  3234.         WFE_SetLO_Color( RGB(255,0,255),
  3235.                          &pColorData->ColorActiveLink );
  3236.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3237.     }
  3238.  
  3239.     pColorData = AddNewColorData( m_pSchemeData );
  3240.     if ( pColorData ) {
  3241.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_YELLOW));
  3242.         WFE_SetLO_Color( RGB(64,0,64), 
  3243.                          &pColorData->ColorText );
  3244.         WFE_SetLO_Color( RGB(255,255,128),
  3245.                          &pColorData->ColorBackground );
  3246.         WFE_SetLO_Color( RGB(0,0,255),
  3247.                          &pColorData->ColorLink );
  3248.         WFE_SetLO_Color( RGB(0,128, 0),
  3249.                          &pColorData->ColorFollowedLink );
  3250.         WFE_SetLO_Color( RGB(255,0,128),
  3251.                          &pColorData->ColorActiveLink );
  3252.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3253.     }
  3254.  
  3255.     pColorData = AddNewColorData( m_pSchemeData );
  3256.     if ( pColorData ) {
  3257.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_LTBLUE));
  3258.         WFE_SetLO_Color( RGB(0,0,0), 
  3259.                          &pColorData->ColorText );
  3260.         WFE_SetLO_Color( RGB(192,192,255),
  3261.                          &pColorData->ColorBackground );
  3262.         WFE_SetLO_Color( RGB(0,0,255),
  3263.                          &pColorData->ColorLink );
  3264.         WFE_SetLO_Color( RGB(128,0,128),
  3265.                          &pColorData->ColorFollowedLink );
  3266.         WFE_SetLO_Color( RGB(255,0,128),
  3267.                          &pColorData->ColorActiveLink );
  3268.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3269.     }
  3270.  
  3271.     pColorData = AddNewColorData( m_pSchemeData );
  3272.     if ( pColorData ) {
  3273.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLACK_ON_MEDBLUE));
  3274.         WFE_SetLO_Color( RGB(0,0,0), 
  3275.                          &pColorData->ColorText );
  3276.         WFE_SetLO_Color( RGB(128,128,192),
  3277.                          &pColorData->ColorBackground );
  3278.         WFE_SetLO_Color( RGB(255,255,255),
  3279.                          &pColorData->ColorLink );
  3280.         WFE_SetLO_Color( RGB(128,0,128),
  3281.                          &pColorData->ColorFollowedLink );
  3282.         WFE_SetLO_Color( RGB(255,255,0),
  3283.                          &pColorData->ColorActiveLink );
  3284.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3285.     }
  3286.  
  3287.     pColorData = AddNewColorData( m_pSchemeData );
  3288.     if ( pColorData ) {
  3289.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_BLUE_ON_ORANGE));
  3290.         WFE_SetLO_Color( RGB(0,0,128), 
  3291.                          &pColorData->ColorText );
  3292.         WFE_SetLO_Color( RGB(255,192,64),
  3293.                          &pColorData->ColorBackground );
  3294.         WFE_SetLO_Color( RGB(0,0,255),
  3295.                          &pColorData->ColorLink );
  3296.         WFE_SetLO_Color( RGB(0,128,0),
  3297.                          &pColorData->ColorFollowedLink );
  3298.         WFE_SetLO_Color( RGB(0,255,255),
  3299.                          &pColorData->ColorActiveLink );
  3300.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3301.     }
  3302.  
  3303.     pColorData = AddNewColorData( m_pSchemeData );
  3304.     if ( pColorData ) {
  3305.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_BLACK));
  3306.         WFE_SetLO_Color( RGB(255,255,255), 
  3307.                          &pColorData->ColorText );
  3308.         WFE_SetLO_Color( RGB(0,0,0),
  3309.                          &pColorData->ColorBackground );
  3310.         WFE_SetLO_Color( RGB(255,255,0),
  3311.                          &pColorData->ColorLink );
  3312.         WFE_SetLO_Color( RGB(192,192,192),
  3313.                          &pColorData->ColorFollowedLink );
  3314.         WFE_SetLO_Color( RGB(192,255,192),
  3315.                          &pColorData->ColorActiveLink );
  3316.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3317.     }
  3318.  
  3319.     pColorData = AddNewColorData( m_pSchemeData );
  3320.     if ( pColorData ) {
  3321.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_GREEN));
  3322.         WFE_SetLO_Color( RGB(255,255,255), 
  3323.                          &pColorData->ColorText );
  3324.         WFE_SetLO_Color( RGB(0,64,0),
  3325.                          &pColorData->ColorBackground );
  3326.         WFE_SetLO_Color( RGB(255,255,0),
  3327.                          &pColorData->ColorLink );
  3328.         WFE_SetLO_Color( RGB(128,255,128),
  3329.                          &pColorData->ColorFollowedLink );
  3330.         WFE_SetLO_Color( RGB(0,255,64),
  3331.                          &pColorData->ColorActiveLink );
  3332.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3333.     }
  3334.  
  3335.     pColorData = AddNewColorData( m_pSchemeData );
  3336.     if ( pColorData ) {
  3337.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_BLUE));
  3338.         WFE_SetLO_Color( RGB(255,255,255), 
  3339.                          &pColorData->ColorText );
  3340.         WFE_SetLO_Color( RGB(0,0,128),
  3341.                          &pColorData->ColorBackground );
  3342.         WFE_SetLO_Color( RGB(255,255,0),
  3343.                          &pColorData->ColorLink );
  3344.         WFE_SetLO_Color( RGB(128,128,255),
  3345.                          &pColorData->ColorFollowedLink );
  3346.         WFE_SetLO_Color( RGB(255,0,255),
  3347.                          &pColorData->ColorActiveLink );
  3348.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3349.     }
  3350.  
  3351.     pColorData = AddNewColorData( m_pSchemeData );
  3352.     if ( pColorData ) {
  3353.         pColorData->pSchemeName = XP_STRDUP(szLoadString(IDS_WHITE_ON_VIOLET));
  3354.         WFE_SetLO_Color( RGB(255,255,255), 
  3355.                          &pColorData->ColorText );
  3356.         WFE_SetLO_Color( RGB(128,0,128),
  3357.                          &pColorData->ColorBackground );
  3358.         WFE_SetLO_Color( RGB(0,255,255),
  3359.                          &pColorData->ColorLink );
  3360.         WFE_SetLO_Color( RGB(128,255,255),
  3361.                          &pColorData->ColorFollowedLink );
  3362.         WFE_SetLO_Color( RGB(0,255,0),
  3363.                          &pColorData->ColorActiveLink );
  3364.         pSchemeListBox->AddString(pColorData->pSchemeName);
  3365.     }
  3366.  
  3367.     COLORREF tmpColor,defColor;
  3368.     XP_Bool bCust;
  3369.     // Get Browser preference colors
  3370.     PREF_GetColorPrefDWord("browser.foreground_color",&tmpColor);
  3371.     PREF_GetDefaultColorPrefDWord("browser.foreground_color",&defColor);
  3372.     PREF_GetBoolPref("browser.custom_text_color",&bCust);
  3373.     m_crBrowserText = bCust ? tmpColor : defColor;
  3374.  
  3375.     PREF_GetColorPrefDWord("browser.anchor_color",&tmpColor);
  3376.     PREF_GetDefaultColorPrefDWord("browser.anchor_color",&defColor);
  3377.     PREF_GetBoolPref("browser.custom_link_color",&bCust);
  3378.     m_crBrowserLink = bCust ? tmpColor : defColor;
  3379.  
  3380.     
  3381.     PREF_GetColorPrefDWord("browser.visited_color",&tmpColor);
  3382.     PREF_GetDefaultColorPrefDWord("browser.visited_color",&defColor);
  3383.     PREF_GetBoolPref("browser.custom_visited_color",&bCust);
  3384.     m_crBrowserFollowedLink = bCust ? tmpColor : defColor;
  3385.  
  3386.     m_crBrowserBackground = prefInfo.m_rgbBackgroundColor;
  3387.  
  3388.     // m_pPageData may be NULL if we are not an Editor
  3389.     // (preferences dialog called from a browser)
  3390.     //
  3391.     // We are in Document Properties Mode
  3392.     // Initialize from current document
  3393.     // Note: If the color isn't set,
  3394.     //       this will get the color from display master colors
  3395.     m_crCustomBackground = WFE_LO2COLORREF( m_pPageData->pColorBackground,LO_COLOR_BG );
  3396.     m_crCustomText = WFE_LO2COLORREF( m_pPageData->pColorText, LO_COLOR_FG );
  3397.     m_crCustomLink = WFE_LO2COLORREF( m_pPageData->pColorLink, LO_COLOR_LINK );
  3398.     m_crCustomActiveLink = WFE_LO2COLORREF( m_pPageData->pColorActiveLink, LO_COLOR_ALINK );
  3399.     m_crCustomFollowedLink = WFE_LO2COLORREF( m_pPageData->pColorFollowedLink, LO_COLOR_VLINK );
  3400.  
  3401.     if (( m_pPageData->pBackgroundImage )&&( XP_STRLEN(m_pPageData->pBackgroundImage) )) {
  3402.         m_csBackgroundImage = m_pPageData->pBackgroundImage;
  3403.         // Set checkbox - we have an image
  3404.         ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(1);
  3405.     } else {
  3406.         // Get the default image from preferences in case they want to use it
  3407.         char * szBack = NULL;
  3408.         PREF_CopyCharPref("editor.background_image",&szBack);
  3409.         m_csBackgroundImage = szBack;
  3410.         XP_FREEIF(szBack);
  3411.         // But DON'T set the checkbox -- image will not be used
  3412.         ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
  3413.     }
  3414.  
  3415.     // If ANY color is set, then we will assume "Custom" mode
  3416.     m_bCustomColors = 
  3417.         ( m_pPageData->pColorBackground ||
  3418.           m_pPageData->pColorText ||
  3419.           m_pPageData->pColorLink ||
  3420.           m_pPageData->pColorActiveLink ||
  3421.           m_pPageData->pColorFollowedLink );
  3422.     
  3423.     // Save current state so we don't repaint unnecessarily
  3424.     m_bWasCustomColors = m_bCustomColors;
  3425.     
  3426.     // Flag to leave image at original location and not save with page
  3427.     m_bNoSave = m_pPageData->bBackgroundNoSave;
  3428.     
  3429.     if( m_bCustomColors ){
  3430.         // We will start in Custom Colors mode
  3431.         // Redraw only if current state is Browser colors
  3432.         // Don't unselect scheme
  3433.         UseCustomColors(!m_bWasCustomColors, FALSE);
  3434.     } else {
  3435.         // We will start with Browser colors
  3436.         // Don't do update stuff
  3437.         UseBrowserColors(FALSE);
  3438.     }
  3439.  
  3440.     // Initialize radio buttons and color swatches
  3441.     ((CButton*)GetDlgItem(IDC_SET_DOC_COLORS))->SetCheck( m_bCustomColors ? 1 : 0 );
  3442.     ((CButton*)GetDlgItem(IDC_USE_BROWSER_COLORS))->SetCheck( m_bCustomColors ? 0 : 1 );
  3443.  
  3444.     // Disables Apply button (probably don't need to do this)
  3445.     SetModified(FALSE);
  3446.     UpdateData(FALSE);
  3447.     return(TRUE);
  3448. }
  3449.  
  3450. // Use bUpdateControls = FALSE if initializing,
  3451. // Use TRUE when switching from CustomColor state to Browser colors
  3452. void CDocColorPage::UseBrowserColors(BOOL bRedraw)
  3453. {
  3454.     m_bCustomColors = m_bWasCustomColors = FALSE;
  3455.     ((CButton*)GetDlgItem(IDC_SET_DOC_COLORS))->SetCheck(0);
  3456.     ((CButton*)GetDlgItem(IDC_USE_BROWSER_COLORS))->SetCheck(1);
  3457.  
  3458.     // Initialize from current preferences
  3459.     m_crBackground = m_crBrowserBackground;
  3460.     m_crText = m_crBrowserText;
  3461.     m_crLink = m_crBrowserLink;
  3462.     // Browser doesn't store this color
  3463.     m_crActiveLink = m_crBrowserLink;
  3464.     m_crFollowedLink = m_crBrowserFollowedLink;
  3465.  
  3466.     if( bRedraw ){
  3467.         Invalidate(FALSE);
  3468.     }
  3469.     SetModified(TRUE);
  3470. }
  3471.  
  3472. // Redraw dialog to show color swatches -- use bRedraw = FALSE if no colors changing
  3473. void CDocColorPage::UseCustomColors(BOOL bRedraw, BOOL bUnselectScheme)
  3474. {
  3475.     m_bCustomColors = m_bWasCustomColors = TRUE;
  3476.     ((CButton*)GetDlgItem(IDC_SET_DOC_COLORS))->SetCheck(1);
  3477.     ((CButton*)GetDlgItem(IDC_USE_BROWSER_COLORS))->SetCheck(0);
  3478.  
  3479.     if( bUnselectScheme ){
  3480.         // Get selected scheme name
  3481.         // (Also gets background image image name, which we ignore here)
  3482.         UpdateData(TRUE);
  3483.         // TODO: Modify this in the future to
  3484.         //   reset only if not one of built-in
  3485.         //   schemes?
  3486.         // Get currently-selected scheme
  3487.         //  to use as default name for saving
  3488.         m_csSaveScheme = m_csSelectedScheme;
  3489.         
  3490.         // Unselect scheme list when editing built-in schemes,
  3491.         //  to remove impression that user can modify them
  3492.         ((CComboBox*)GetDlgItem(IDC_SCHEME_LIST))->SetCurSel(-1);
  3493.     }
  3494.     m_crBackground = m_crCustomBackground;
  3495.     m_crText = m_crCustomText;
  3496.     m_crLink = m_crCustomLink;
  3497.     m_crActiveLink = m_crCustomActiveLink;
  3498.     m_crFollowedLink = m_crCustomFollowedLink;
  3499.  
  3500.     if( bRedraw ){
  3501.         // Redraw color swatches and text samples
  3502.         Invalidate(FALSE);
  3503.     }
  3504.     // Set Apply button states if we are in Properties mode
  3505.     SetModified(TRUE);
  3506. }
  3507.  
  3508. BOOL CDocColorPage::OnKillActive()
  3509. {
  3510.     if(m_bActivated){
  3511.         if( !UpdateData(TRUE) ){
  3512.             return FALSE;
  3513.         }
  3514.         if ( !m_csBackgroundImage.IsEmpty() ) {
  3515.             if ( m_bImageChanged && !m_bValidImage ) {
  3516.                 if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
  3517.                     !wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/ ) ){
  3518.                     ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
  3519.                     return FALSE;
  3520.                 }
  3521.                 // Send changed image back to editbox in case this is Apply usage
  3522.                 UpdateData(FALSE);
  3523.             }
  3524.         }
  3525.         if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
  3526.             !m_csBackgroundImage.IsEmpty() ){
  3527.             int iLastDot = m_csBackgroundImage.ReverseFind('.');
  3528.             CString csExt;
  3529.             if(iLastDot > 0)
  3530.                 csExt= m_csBackgroundImage.Mid(iLastDot);
  3531.  
  3532.             //we must check to see if file is a bmp!
  3533.             if (0 == csExt.CompareNoCase(".bmp"))
  3534.             {
  3535.                 char *t_outputfilename=wfe_ConvertImage(m_csBackgroundImage.GetBuffer(0),(void *)this,m_pMWContext);
  3536.                 if (t_outputfilename)
  3537.                 {
  3538.                     m_csBackgroundImage=t_outputfilename;
  3539.                     wfe_ValidateImage( m_pMWContext, m_csBackgroundImage );
  3540.                     XP_FREE(t_outputfilename);
  3541.                     UpdateData(FALSE);//we need to update m_csImage!
  3542.                 }
  3543.                 else 
  3544.                     return FALSE;
  3545.             }
  3546.         }
  3547.     }
  3548.     return TRUE;
  3549. }
  3550.  
  3551. void CDocColorPage::OnHelp() 
  3552. {
  3553.     NetHelp(HELP_DOC_PROPS_APPEARANCE);
  3554. }
  3555.  
  3556. void CDocColorPage::OnOK() 
  3557. {
  3558.     //Note: Get and Validate data done in OnKillActive()
  3559.     CPropertyPage::OnOK();
  3560.  
  3561.     // never visited this page,
  3562.     // or no change when used in Doc. Properties mode -- don't bother
  3563.     if( !m_bActivated ||
  3564.         !IS_APPLY_ENABLED(this) ){
  3565.         return;
  3566.     }    
  3567.  
  3568.     // Save settings for current document
  3569.     // Erase current background image in doc
  3570.     if ( m_pPageData->pBackgroundImage ) {
  3571.         XP_FREE( m_pPageData->pBackgroundImage );
  3572.         m_pPageData->pBackgroundImage = NULL;
  3573.     }
  3574.     if ( m_bCustomColors ) {
  3575.         // Set all custom colors
  3576.         WFE_SetLO_ColorPtr( m_crCustomText, &m_pPageData->pColorText );
  3577.         WFE_SetLO_ColorPtr( m_crCustomLink, &m_pPageData->pColorLink );
  3578.         WFE_SetLO_ColorPtr( m_crCustomActiveLink, &m_pPageData->pColorActiveLink );
  3579.         WFE_SetLO_ColorPtr( m_crCustomFollowedLink, &m_pPageData->pColorFollowedLink );
  3580.         // Set color even if we use an image
  3581.         // (Color tag is written to doc, but image tag overrides)
  3582.         WFE_SetLO_ColorPtr( m_crCustomBackground, &m_pPageData->pColorBackground );
  3583.  
  3584.     } else {
  3585.         // Use browser colors means storing no tags in document
  3586.         // Clear all colors and background image to set the document's tags
  3587.         // Note: We ignore the Browser's background image, 
  3588.         //   based on the judgement that if they don't want colors,
  3589.         //   then the browser's image would be irrelavent (and distracting) while editing
  3590.         WFE_FreeLO_Color( &m_pPageData->pColorText );
  3591.         WFE_FreeLO_Color( &m_pPageData->pColorLink );
  3592.         WFE_FreeLO_Color( &m_pPageData->pColorActiveLink );
  3593.         WFE_FreeLO_Color( &m_pPageData->pColorFollowedLink );
  3594.         WFE_FreeLO_Color( &m_pPageData->pColorBackground );
  3595.     }
  3596.  
  3597.     if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
  3598.         !m_csBackgroundImage.IsEmpty() ){
  3599.         m_pPageData->pBackgroundImage = XP_STRDUP(m_csBackgroundImage);
  3600.  
  3601.         // Save state of flag from checkbox
  3602.         m_pPageData->bBackgroundNoSave = m_bNoSave;
  3603.     }
  3604.     
  3605.     // Disable Apply an change "OK" to "Close"
  3606.     OkToClose();
  3607.     // Clear data-modified flag
  3608.     SetModified(FALSE);
  3609.  
  3610.     // This sets tag data for doc and calls front end
  3611.     //  to setbackground colors and image
  3612.     EDT_SetPageData(m_pMWContext, m_pPageData);
  3613.  
  3614.     // This forces redraw of entire window
  3615.     //  (to correct paint bug: missing redraw areas at top of window above cursor)
  3616.     HWND hView = PANECX(m_pMWContext)->GetPane();
  3617.     if( hView ){
  3618.         ::InvalidateRect(hView, NULL, TRUE);
  3619.     }
  3620.  
  3621.     // This forces redraw of entire window
  3622.     //  (there is some missing redraw areas at top of window)
  3623.     ::InvalidateRect(PANECX(m_pMWContext)->GetPane(), NULL, TRUE);
  3624.  
  3625.     if( ((CButton*)GetDlgItem(IDC_USE_AS_DEFAULT))->GetCheck() ){
  3626.         // Save current settings to Preferences
  3627.         if( ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck() &&
  3628.             !m_csBackgroundImage.IsEmpty() ){
  3629.             PREF_SetBoolPref("editor.use_background_image",TRUE);
  3630.             PREF_SetCharPref("editor.background_image",LPCSTR(m_csBackgroundImage));
  3631.         } else {
  3632.             PREF_SetBoolPref("editor.use_background_image",FALSE);
  3633.         }
  3634.  
  3635.         if ( m_bCustomColors ) {
  3636.             PREF_SetBoolPref("editor.use_custom_colors",TRUE);
  3637.             PREF_SetCharPref("editor.color_scheme",(char*)LPCSTR(m_csSelectedScheme));
  3638.  
  3639.             PREF_SetColorPrefDWord("editor.text_color",m_crCustomText);
  3640.             PREF_SetColorPrefDWord("editor.link_color",m_crCustomLink);
  3641.             PREF_SetColorPrefDWord("editor.active_link_color",m_crCustomActiveLink);
  3642.             PREF_SetColorPrefDWord("editor.followed_link_color",m_crCustomFollowedLink);
  3643.             PREF_SetColorPrefDWord("editor.background_color",m_crCustomBackground);
  3644.         } else {
  3645.             // Note: don't change previous color preferences
  3646.             PREF_SetBoolPref("editor.use_custom_colors",FALSE);
  3647.         }
  3648.     }
  3649. }
  3650.  
  3651. void CDocColorPage::OnUseAsDefault()
  3652. {
  3653.     SetModified(TRUE);
  3654. }
  3655.  
  3656. void CDocColorPage::OnColorsRadioButtons() 
  3657. {
  3658.     // Get checkbox state and change colors appropriately
  3659.     //  but only if different than previous mode
  3660.     m_bCustomColors = IsDlgButtonChecked(IDC_SET_DOC_COLORS);
  3661.     if(m_bWasCustomColors != m_bCustomColors){
  3662.         if(m_bCustomColors){
  3663.             UseCustomColors();
  3664.         } else {
  3665.             UseBrowserColors();
  3666.         }
  3667.         // Send the appropriate string to the background image editbox
  3668.         UpdateData(FALSE);
  3669.     }
  3670. }
  3671.  
  3672. void CDocColorPage::OnRemoveScheme() 
  3673. {
  3674.     SetModified(TRUE);
  3675. }
  3676.  
  3677. void CDocColorPage::OnSaveScheme() 
  3678. {
  3679.     SetModified(TRUE);
  3680. }
  3681.  
  3682. void CDocColorPage::OnSelchangeSchemeList() 
  3683. {
  3684.     // Get data - we want selected color scheme
  3685.     UpdateData(TRUE);
  3686.     if ( m_csSelectedScheme.IsEmpty() ) {
  3687.         return;
  3688.     }
  3689.  
  3690.     // Find the scheme in the list and extract color info
  3691.     EDT_ColorSchemeData *pColorData;
  3692.     XP_List * list_ptr = m_pSchemeData;
  3693.     while ((pColorData = (EDT_ColorSchemeData *)XP_ListNextObject(list_ptr))) {
  3694.         if ( 0 == XP_STRCMP(pColorData->pSchemeName, m_csSelectedScheme) ) {
  3695.             m_crCustomText = 
  3696.                 WFE_LO2COLORREF( &pColorData->ColorText, LO_COLOR_FG );
  3697.             m_crCustomLink = 
  3698.                 WFE_LO2COLORREF( &pColorData->ColorLink, LO_COLOR_LINK );
  3699.             m_crCustomActiveLink = 
  3700.                 WFE_LO2COLORREF( &pColorData->ColorActiveLink, LO_COLOR_ALINK );
  3701.             m_crCustomFollowedLink = 
  3702.                 WFE_LO2COLORREF( &pColorData->ColorFollowedLink, LO_COLOR_VLINK );
  3703.             m_crCustomBackground = 
  3704.                 WFE_LO2COLORREF( &pColorData->ColorBackground, LO_COLOR_BG );
  3705.             
  3706.             if ( pColorData->pBackgroundImage ) {
  3707.                 // Scheme may include a background image...
  3708.                 ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(1);
  3709.                 m_csBackgroundImage = pColorData->pBackgroundImage;
  3710.             }
  3711.             // ...but if scheme doesn't have image, then leave existing
  3712.             //   image and checkbox state
  3713.             break;
  3714.         }
  3715.     }
  3716.     // Do repaint, but don't unselect the scheme listbox
  3717.     UseCustomColors(TRUE, FALSE);
  3718. }
  3719.  
  3720. BOOL CDocColorPage::ChooseColor(COLORREF * pColor, CColorButton * pButton, COLORREF crDefault )
  3721. {
  3722.        RECT rect;
  3723.     pButton->GetWindowRect(&rect);
  3724.     CColorPicker ColorPicker(this, m_pMWContext, m_bCustomColors ? *pColor : DEFAULT_COLORREF, crDefault, 0, &rect);
  3725.     COLORREF crNew = ColorPicker.GetColor();
  3726.     if( crNew != CANCEL_COLORREF ){
  3727.         if( crNew == DEFAULT_COLORREF){
  3728.             *pColor = crDefault;
  3729.         } else {
  3730.             *pColor = crNew;
  3731.         }
  3732.         // Send new color to control
  3733.         UpdateData(FALSE);        
  3734.         // We must be in custom color mode now
  3735.         UseCustomColors();
  3736.         pButton->Update();
  3737.         return TRUE;
  3738.     }
  3739.     return FALSE;
  3740. }
  3741.  
  3742. void CDocColorPage::OnChooseTextColor() 
  3743. {
  3744.     ChooseColor(&m_crCustomText, &m_TextColorButton, m_crBrowserText);
  3745. }
  3746.  
  3747. void CDocColorPage::OnChooseLinkColor() 
  3748. {
  3749.     ChooseColor(&m_crCustomLink, &m_LinkColorButton, m_crBrowserLink );
  3750. }
  3751.  
  3752. void CDocColorPage::OnChooseActivelinkColor() 
  3753. {
  3754.     ChooseColor(&m_crCustomActiveLink, &m_ActiveLinkColorButton, m_crBrowserLink);
  3755. }
  3756.  
  3757. void CDocColorPage::OnChooseFollowedlinkColor() 
  3758. {
  3759.     ChooseColor(&m_crCustomFollowedLink, &m_FollowedLinkColorButton, m_crBrowserFollowedLink);
  3760. }
  3761.  
  3762. void CDocColorPage::OnChooseBkgrndColor() 
  3763. {
  3764.     if ( ChooseColor(&m_crCustomBackground, &m_BackgroundColorButton, m_crBrowserBackground) ) {
  3765.         // Change to custom colors if  we were Browser mode       
  3766.         UseCustomColors(!m_bWasCustomColors);
  3767.     }
  3768. }
  3769.  
  3770. void CDocColorPage::OnChangeBkgrndImage() 
  3771. {
  3772.     // Set flags to trigger validation on Killfocus
  3773.     m_bValidImage = FALSE;
  3774.     m_bImageChanged = TRUE;
  3775.     
  3776.     UpdateData(TRUE);
  3777.     CString csTemp = m_csBackgroundImage;
  3778.     csTemp.TrimLeft();
  3779.     csTemp.TrimRight();
  3780.  
  3781.     // Set checkbox if there are any characters, clear if empty
  3782.     ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(!csTemp.IsEmpty());
  3783.     SetModified(TRUE);
  3784.     // NEW: Allow selecting an image if we are in Browser color mode
  3785.     // UseCustomColors(!m_bWasCustomColors);
  3786. }
  3787.  
  3788. void CDocColorPage::OnKillfocusBkgrndImage() 
  3789. {
  3790. #if 0
  3791. // Use this if we want to validate as soon as they leave the editbox
  3792.     // Get the image name, make it a relative file-type URL,
  3793.     //  then send it back to editbox
  3794.     if( m_bImageChanged &&
  3795.         UpdateData(TRUE) ){
  3796.         if( !wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/  ) ){
  3797.             ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
  3798.         }
  3799.  
  3800.         m_bValidImage = TRUE;
  3801.         UpdateData(FALSE);
  3802.     }
  3803. #endif
  3804. }
  3805.  
  3806. // Called from the View after saving file to disk -- has new background
  3807. //   image URL relative to current document
  3808. void CDocColorPage::SetImageFileSaved(char * pImageURL)
  3809. {
  3810.     m_csBackgroundImage = pImageURL;
  3811.     UpdateData(FALSE);
  3812. }
  3813.  
  3814. void CDocColorPage::OnUseBkgrndImage() 
  3815. {
  3816.     int iUseImageBackground = ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->GetCheck();;
  3817.     SetModified(TRUE);
  3818.     if( iUseImageBackground ){
  3819.         // User decided to use the image, so do trigger validation
  3820.         if( !wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/  ) ){
  3821.             ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
  3822.         }
  3823.         m_bValidImage = TRUE;
  3824.     }
  3825.     // TODO: Try to display image in our preview box
  3826.     // Need to load file and convert to bitmap
  3827.     // Redraw only if current state is Browser colors
  3828.     // NEW: Allow selecting an image if we are in Browser color mode
  3829. //    UseCustomColors(!m_bWasCustomColors);
  3830. }
  3831.  
  3832. void CDocColorPage::OnChooseBkgrndImage() 
  3833. {
  3834.     char * szFilename = wfe_GetExistingImageFileName(this->m_hWnd, 
  3835.                                          szLoadString(IDS_SELECT_IMAGE), TRUE);
  3836.     if ( szFilename == NULL ){
  3837.         return;
  3838.     }
  3839.     m_csBackgroundImage = szFilename;
  3840.     if( !wfe_ValidateImage( m_pMWContext, m_csBackgroundImage, FALSE /*TRUE*/  ) ){
  3841.         ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(0);
  3842.     }
  3843.  
  3844.     // Send new name to editbox
  3845.     UpdateData(FALSE);
  3846.  
  3847.     XP_FREE( szFilename );
  3848.     m_bValidImage = TRUE;
  3849.     m_bImageChanged = FALSE;
  3850.  
  3851.     // Note: allow background image without forcing custom colors
  3852.     ((CButton*)GetDlgItem(IDC_BKGRND_USE_IMAGE))->SetCheck(1);
  3853.     SetModified(TRUE);
  3854. }
  3855.  
  3856. void CDocColorPage::OnPaint() 
  3857. {
  3858.     CWnd *pPreview = GetDlgItem(IDC_DOC_COLOR_PREVIEW);
  3859.  
  3860.     // TODO: Quit here if we don't use text preview in "Use Browser Colors" mode
  3861.  
  3862.     // Wierd Windows! We must do this else
  3863.     //   no painting at all occurs!
  3864.     CPaintDC dc(this); // device context for painting
  3865.  
  3866.     // Get the DC to the Preview window
  3867.     CDC * pDC = pPreview->GetDC();
  3868.     if( !pDC ) return;
  3869.     CRect cRect;
  3870.  
  3871.     HPALETTE hOldPal = NULL;
  3872.     if( m_hPal ){
  3873.         hOldPal = ::SelectPalette( pDC->m_hDC, m_hPal, FALSE );
  3874.     }
  3875.  
  3876.     // find out how much area we can draw into
  3877.     pPreview->GetClientRect(&cRect);
  3878.  
  3879.     // color for the inside
  3880.     CBrush brush(m_crBackground|0x02000000); // Like PALETTERGB
  3881.     CBrush * pOldBrush = (CBrush *) pDC->SelectObject(&brush);
  3882.  
  3883.     pDC->LPtoDP(&cRect);
  3884.  
  3885.     cRect.InflateRect(-1,-1);
  3886.  
  3887.     // draw the background
  3888.     pDC->FillRect(cRect, &brush);
  3889.  
  3890.     // set the background color
  3891.     pDC->SetBkColor(m_crBackground);
  3892.     pDC->SetTextColor(m_crText);
  3893.     pDC->SetBkMode(TRANSPARENT);
  3894.  
  3895.     // Draw 4 sample text strings
  3896.     CString csText = szLoadString(IDS_TEXT);
  3897.  
  3898.     int iNextLine = (cRect.Height() - 2) / 4;
  3899.     int iTextTop = 2;
  3900.     int iTextLeft = 6;
  3901.  
  3902.     char* csSample = szLoadString(IDS_TEXT);
  3903.     CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
  3904.  
  3905.     CSize sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
  3906.     csSample = szLoadString(IDS_LINK_TEXT);
  3907.     pDC->SetTextColor(m_crLink);
  3908.  
  3909.     // This puts "Link text" on 2nd line:
  3910.     iTextTop += iNextLine;
  3911.     CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
  3912.  
  3913.     // Underline link samples
  3914.     sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
  3915.     CPen penLink(PS_SOLID, 2, m_crLink);
  3916.     CPen *pOldPen = pDC->SelectObject(&penLink);
  3917.  
  3918.     pDC->MoveTo(iTextLeft, iTextTop + sizeText.cy + 1);
  3919.     pDC->LineTo(iTextLeft + sizeText.cx, iTextTop + sizeText.cy + 1);
  3920.     
  3921.     // Move to a new line of text
  3922.     iTextTop += iNextLine;
  3923.     csSample = szLoadString(IDS_ACTIVE_LINK_TEXT);
  3924.     sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
  3925.     pDC->SetTextColor(m_crActiveLink);
  3926.     CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
  3927.     CPen penActive(PS_SOLID, 2, m_crActiveLink);
  3928.     pDC->SelectObject(&penActive);
  3929.     pDC->MoveTo(iTextLeft, iTextTop + sizeText.cy + 1);
  3930.     pDC->LineTo(iTextLeft + sizeText.cx, iTextTop + sizeText.cy + 1);
  3931.     
  3932.     // Next line
  3933.     iTextTop += iNextLine;
  3934.     csSample = szLoadString(IDS_FOLLOWED_LINK);
  3935.     sizeText = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), csSample, strlen(csSample) );
  3936.     pDC->SetTextColor(m_crFollowedLink);
  3937.     CIntlWin::TextOut(0, pDC->GetSafeHdc(), iTextLeft, iTextTop, csSample, strlen(csSample));
  3938.     CPen penFollowed(PS_SOLID, 2, m_crFollowedLink);
  3939.     pDC->SelectObject(&penFollowed);
  3940.     pDC->MoveTo(iTextLeft, iTextTop + sizeText.cy + 1);
  3941.     pDC->LineTo(iTextLeft + sizeText.cx, iTextTop + sizeText.cy + 1);
  3942.  
  3943.     pDC->SelectObject(pOldBrush);
  3944.     pDC->SelectObject(pOldPen);
  3945.  
  3946.     if(m_hPal){
  3947.         ::SelectPalette( pDC->m_hDC, hOldPal, FALSE );
  3948.     }
  3949.     // give the CDC back to the system
  3950.     pPreview->ReleaseDC(pDC);
  3951. }
  3952.  
  3953.  
  3954. void CDocColorPage::OnNoSave() 
  3955. {
  3956.     SetModified(TRUE);
  3957. }
  3958.  
  3959. ////////////////////////////////////////////////////
  3960. CDocMetaPage::CDocMetaPage(CWnd* pParent, MWContext * pMWContext,
  3961.                            CEditorResourceSwitcher * pResourceSwitcher)
  3962.     : CNetscapePropertyPage(CDocMetaPage::IDD),
  3963.       m_bActivated(FALSE),
  3964.       m_pMWContext(pMWContext),
  3965.       m_pResourceSwitcher(pResourceSwitcher)
  3966. {
  3967.     //{{AFX_DATA_INIT(CDocMetaPage)
  3968.     //}}AFX_DATA_INIT
  3969.     ASSERT(pMWContext);
  3970.  
  3971. #ifdef XP_WIN32
  3972.     // Set the hInstance so we get template from editor's resource DLL
  3973.     m_psp.hInstance = AfxGetResourceHandle();
  3974. #endif
  3975. }
  3976.  
  3977. BOOL CDocMetaPage::OnSetActive() 
  3978. {
  3979.     if(m_pResourceSwitcher && !m_bActivated){
  3980.         // We must be sure we have switched
  3981.         //  the first time here - before dialog creation
  3982.         m_pResourceSwitcher->switchResources();
  3983.     }
  3984.     if(!CPropertyPage::OnSetActive())
  3985.         return(FALSE);
  3986.  
  3987.     if(m_bActivated)
  3988.         return(TRUE);
  3989.  
  3990.     // Switch back to EXE's resources
  3991.     if( m_pResourceSwitcher ){
  3992.         m_pResourceSwitcher->Reset();
  3993.     }
  3994.  
  3995.     ((CEdit*)GetDlgItem(IDC_VAR_NAME))->LimitText(MAX_META_NAME_LEN);
  3996.     ((CEdit*)GetDlgItem(IDC_VAR_VALUE))->LimitText(MAX_META_VALUE_LEN);
  3997.  
  3998.     // Get all the items for the lists editbox
  3999.     GetMetaData();
  4000.     
  4001.     // Setup list for a new meta item
  4002.     ((CListBox*)GetDlgItem(IDC_META_LIST))->SetCurSel(m_iMetaCount);
  4003.  
  4004.     m_bActivated = TRUE;
  4005.     return(TRUE);
  4006. }
  4007.  
  4008. void CDocMetaPage::OnSelchangeEquivList() 
  4009. {
  4010.     CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
  4011.     CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
  4012.     
  4013.     int iSel = pEquivList->GetCurSel();
  4014.     BOOL bCanSetOrDelete = FALSE;
  4015.  
  4016.     // Don't set Name and Value if selecting the last item
  4017.     //   unless we are switch from other list
  4018.     if ( iSel >= 0 &&
  4019.          (-1 != pMetaList->GetCurSel() ||
  4020.           iSel != m_iEquivCount) ) {
  4021.         CString csEntry;
  4022.         CString csName;
  4023.         CString csValue;
  4024.         pEquivList->GetText(iSel, csEntry);
  4025.         if (GetNameAndValue(csEntry, csName, csValue)) {
  4026.             ((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetWindowText( LPCSTR(csName) );
  4027.             ((CEdit*)GetDlgItem(IDC_VAR_VALUE))->SetWindowText( LPCSTR(csValue) );
  4028.             bCanSetOrDelete = TRUE;
  4029.         } else {
  4030.             ClearNameAndValue();
  4031.         }
  4032.     }
  4033.     SetModified(TRUE);
  4034.     // Only one list can be selected at a time
  4035.     // We use selected list as a "radio button" to inform
  4036.     //   user which list the Name/Value pair applies to
  4037.     pMetaList->SetCurSel(-1);
  4038.     EnableButtons(bCanSetOrDelete);
  4039. }
  4040.  
  4041. void CDocMetaPage::OnSelchangeMetaList() 
  4042. {
  4043.     CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
  4044.     CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
  4045.     
  4046.     int iSel = pMetaList->GetCurSel();
  4047.     BOOL bCanSetOrDelete = FALSE;
  4048.  
  4049.     // Don't set Name and Value if selecting the last item
  4050.     //   unless we are switch from other list
  4051.     if ( iSel >= 0 && 
  4052.          (-1 != pEquivList->GetCurSel() ||
  4053.           iSel != m_iMetaCount)) {
  4054.         CString csEntry;
  4055.         CString csName;
  4056.         CString csValue;
  4057.         pMetaList->GetText(iSel, csEntry);
  4058.         if (GetNameAndValue(csEntry, csName, csValue)) {
  4059.             ((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetWindowText( LPCSTR(csName) );
  4060.             ((CEdit*)GetDlgItem(IDC_VAR_VALUE))->SetWindowText( LPCSTR(csValue) );
  4061.             bCanSetOrDelete = TRUE;
  4062.         } else {
  4063.             ClearNameAndValue();
  4064.         }
  4065.     }
  4066.     SetModified(TRUE);
  4067.  
  4068.     // Only one list can be selected at a time
  4069.     pEquivList->SetCurSel(-1);
  4070.     EnableButtons(bCanSetOrDelete);
  4071. }
  4072.  
  4073. // Make clicking below list items the same as 
  4074. //   selecting the last (empty) item so we 
  4075. //   always change lists when clicked on
  4076. void CDocMetaPage::OnSetfocusEquivList() 
  4077. {
  4078.     if (((CListBox*)GetDlgItem(IDC_EQUIV_LIST))->GetCurSel() == -1 ) {
  4079.         ((CListBox*)GetDlgItem(IDC_EQUIV_LIST))->SetCurSel(m_iEquivCount);
  4080.         OnSelchangeEquivList();
  4081.     }
  4082. }
  4083.  
  4084. void CDocMetaPage::OnSetfocusMetaList() 
  4085. {
  4086.     if (((CListBox*)GetDlgItem(IDC_META_LIST))->GetCurSel() == -1 ) {
  4087.         ((CListBox*)GetDlgItem(IDC_META_LIST))->SetCurSel(m_iMetaCount);
  4088.         OnSelchangeMetaList();
  4089.     }
  4090. }
  4091.  
  4092. void CDocMetaPage::OnChangeVarNameOrValue() 
  4093. {
  4094.     CString csName;
  4095.     GetDlgItem(IDC_VAR_NAME)->GetWindowText(csName);
  4096.     CString csValue;
  4097.     GetDlgItem(IDC_VAR_VALUE)->GetWindowText(csValue);
  4098.     CleanupString(csName);
  4099.     CleanupString(csValue);
  4100.     GetDlgItem(IDC_VAR_SET)->EnableWindow(!csName.IsEmpty() && !csValue.IsEmpty());
  4101.     GetDlgItem(IDC_VAR_NEW)->EnableWindow(!csName.IsEmpty() || !csValue.IsEmpty());
  4102.     GetDlgItem(IDC_VAR_DELETE)->EnableWindow(!csName.IsEmpty() );
  4103.     SetModified(TRUE);
  4104. }
  4105.  
  4106. void CDocMetaPage::OnVarSet() 
  4107. {
  4108.     CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
  4109.     CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
  4110.  
  4111.     CString csName;
  4112.     GetDlgItem(IDC_VAR_NAME)->GetWindowText(csName);
  4113.     CString csValue;
  4114.     GetDlgItem(IDC_VAR_VALUE)->GetWindowText(csValue);
  4115.     CleanupString(csName);
  4116.     CleanupString(csValue);
  4117.    
  4118.     
  4119.     if ( !csName.IsEmpty() ) {
  4120.         int iEqual = csName.Find('=');
  4121.         if ( iEqual != -1 ) {
  4122.             csName = csName.Left(iEqual);
  4123.             CleanupString(csName);
  4124.         }
  4125.         CString csSearch = csName + "=";
  4126.         BOOL bEquiv;
  4127.         // We determine which list to use by which was last selected
  4128.         if ( pEquivList->GetCurSel() != -1 ) {
  4129.             SetMetaData(TRUE, CHAR_STR(csName), CHAR_STR(csValue));
  4130.             bEquiv = TRUE;
  4131.         } else {
  4132.             SetMetaData(FALSE, CHAR_STR(csName), CHAR_STR(csValue));
  4133.             bEquiv = FALSE;
  4134.         }
  4135.         GetMetaData();
  4136.  
  4137.         BOOL bCanDelete = FALSE;
  4138.         // Set the selection to the item just set,
  4139.         //  but set to last item if (for some very weird reason) we fail
  4140.         if (bEquiv) {
  4141.             if ( -1 == pEquivList->SelectString(-1,LPCSTR(csSearch)) ) {
  4142.                 pEquivList->SetCurSel(m_iEquivCount);
  4143.             } else {
  4144.                 bCanDelete = TRUE;
  4145.             }
  4146.             pMetaList->SetCurSel(-1);
  4147.         } else {
  4148.             if ( -1 == pMetaList->SelectString(-1,LPCSTR(csSearch)) ) {
  4149.                 pMetaList->SetCurSel(m_iEquivCount);
  4150.             } else {
  4151.                 bCanDelete = TRUE;
  4152.             }
  4153.             pEquivList->SetCurSel(-1);
  4154.         }
  4155.         // We can delete if a non-blank item is selected
  4156.         ((CButton*)GetDlgItem(IDC_VAR_DELETE))->EnableWindow(bCanDelete);
  4157.     }
  4158.    ((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetFocus();
  4159. }
  4160.  
  4161. void CDocMetaPage::OnVarDelete() 
  4162. {
  4163.     CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
  4164.     CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
  4165.  
  4166.     int nSel = pEquivList->GetCurSel();
  4167.     CString csSelString;
  4168.     CString csName;
  4169.     CString csValue;
  4170.     BOOL bEquiv = FALSE;
  4171.     
  4172.     // Get the strings from which ever list has the selected item
  4173.     if ( nSel != -1 ) {
  4174.         pEquivList->GetText(nSel, csSelString);
  4175.         bEquiv = TRUE;
  4176.     } else {
  4177.         nSel = pMetaList->GetCurSel();
  4178.         if ( nSel != -1 ) {
  4179.             pMetaList->GetText(nSel, csSelString);
  4180.         }
  4181.     }
  4182.     if ( nSel != -1 && GetNameAndValue(csSelString, csName, csValue ) ) {
  4183.         // This will delete entry in EDT data with selected Name
  4184.         SetMetaData(bEquiv, CHAR_STR(csName), NULL);
  4185.         // Rebuild the list
  4186.         GetMetaData();
  4187.         SetModified(TRUE);
  4188.     }
  4189.  
  4190.     // Set selection to end of list just deleted
  4191.     //  (or to end of meta list if error deleting)
  4192.     if ( bEquiv ) {
  4193.         pEquivList->SetCurSel(m_iEquivCount);
  4194.     } else {
  4195.         pMetaList->SetCurSel(m_iMetaCount);
  4196.     }
  4197.    ((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetFocus();
  4198. }
  4199.  
  4200. void CDocMetaPage::OnVarNew() 
  4201. {
  4202.     CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
  4203.     CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
  4204.  
  4205.     // Clear the Name-Value edit boxes and 
  4206.     //   remove selection in lists
  4207.     ClearNameAndValue();
  4208.  
  4209.     // Reset the selected item to the blank at end
  4210.     //  of list already selected
  4211.     if ( pEquivList->GetCurSel() != -1 ) {
  4212.         pEquivList->SetCurSel(m_iEquivCount);
  4213.         pMetaList->SetCurSel(-1);
  4214.     } else {
  4215.         pMetaList->SetCurSel(m_iMetaCount);
  4216.     }
  4217.  
  4218.     // Disable all buttons
  4219.     EnableButtons(FALSE);
  4220.     ((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetFocus();
  4221. }
  4222.  
  4223. void CDocMetaPage::EnableButtons(BOOL bEnable)
  4224. {
  4225.     ((CButton*)GetDlgItem(IDC_VAR_SET))->EnableWindow(bEnable);
  4226.     ((CButton*)GetDlgItem(IDC_VAR_DELETE))->EnableWindow(bEnable);
  4227.     ((CButton*)GetDlgItem(IDC_VAR_NEW))->EnableWindow(bEnable);
  4228.  
  4229. void CDocMetaPage::ClearNameAndValue()
  4230. {
  4231.     ((CEdit*)GetDlgItem(IDC_VAR_NAME))->SetWindowText("");
  4232.     ((CEdit*)GetDlgItem(IDC_VAR_VALUE))->SetWindowText("");    
  4233.     EnableButtons(FALSE);
  4234. }
  4235.  
  4236. void CDocMetaPage::GetMetaData() 
  4237. {
  4238.     CListBox *pMetaList = (CListBox*)GetDlgItem(IDC_META_LIST);
  4239.     CListBox *pEquivList = (CListBox*)GetDlgItem(IDC_EQUIV_LIST);
  4240.  
  4241.     // Rebuild our list from the Edit data
  4242.     pEquivList->ResetContent();
  4243.     pMetaList->ResetContent();
  4244.     
  4245.     //   Name = 100, content = 400
  4246.     char pName[MAX_META_NAME_LEN+1];
  4247.     char pValue[MAX_META_VALUE_LEN+1];
  4248.     CString csEntry;
  4249.  
  4250.     m_iEquivCount = 0;
  4251.     m_iMetaCount = 0;
  4252.  
  4253.     int count = EDT_MetaDataCount(m_pMWContext);
  4254.     for ( int i = 0; i < count; i++ ) {
  4255.         EDT_MetaData* pData = EDT_GetMetaData(m_pMWContext, i);
  4256.         PR_snprintf(pName, MAX_META_NAME_LEN, "%s", pData->pName);
  4257.         PR_snprintf(pValue, MAX_META_VALUE_LEN, "%s", pData->pContent);
  4258.         csEntry = pName;
  4259.         csEntry += "=";
  4260.         csEntry += pValue;
  4261.         if ( pData->bHttpEquiv ) {
  4262.             pEquivList->AddString(csEntry);
  4263.             m_iEquivCount++;
  4264.         } else if ( 0 != _stricmp(pName, "Author")         &&
  4265.                     0 != _stricmp(pName, "Description")    &&
  4266.                     0 != _stricmp(pName, "Generator")      &&
  4267.                     0 != _stricmp(pName, "Last-Modified")  &&
  4268.                     0 != _stricmp(pName, "Created")        &&
  4269.                     0 != _stricmp(pName, "Classification") &&
  4270.                     0 != _stricmp(pName, "Keywords")       
  4271.                     /* && 0 != _stricmp(pName, "SourceURL") */
  4272.                     ) {
  4273.             // Skip the fields used in General Info page
  4274.             // TODO: PUT META STRINGS IN RESOURCES?
  4275.             pMetaList->AddString(csEntry);
  4276.             m_iMetaCount++;
  4277.         }
  4278.     }
  4279.     // We add a blank string to each list 
  4280.     //   to ensure a selectable item when none really exists
  4281.     // Note: Listbox should NOT be sorted for this to work right
  4282.     pEquivList->AddString("");
  4283.     pMetaList->AddString("");
  4284.     ClearNameAndValue();
  4285. }
  4286.  
  4287. // Create a MetaData structure and save it 
  4288. // This commits change - NO BUFFERING
  4289. // Be sure to strip off spaces and quotes before calling this
  4290. void CDocMetaPage::SetMetaData(BOOL bHttpEquiv, char * pName, char * pValue)
  4291. {
  4292.     EDT_MetaData *pData = EDT_NewMetaData();
  4293.     if ( pData ) {
  4294.         pData->bHttpEquiv = bHttpEquiv;
  4295.         if ( pName && XP_STRLEN(pName) > 0 ) {
  4296.             pData->pName = XP_STRDUP(pName);
  4297.             if ( pValue && XP_STRLEN(pValue) > 0 ) {
  4298.                 pData->pContent = XP_STRDUP(pValue);
  4299.                 EDT_SetMetaData(m_pMWContext, pData);
  4300.             } else {
  4301.                 // (Don't really need to do this)
  4302.                 pData->pContent = NULL; 
  4303.                 // Remove the item            
  4304.                 EDT_DeleteMetaData(m_pMWContext, pData);
  4305.             }
  4306.             OkToClose();
  4307.         }
  4308.         EDT_FreeMetaData(pData);
  4309.     }
  4310. }
  4311.  
  4312. void CDocMetaPage::OnHelp() 
  4313. {
  4314.     NetHelp(HELP_DOC_PROPS_ADVANCED);
  4315. }
  4316.  
  4317. void CDocMetaPage::OnOK() 
  4318. {
  4319.     CPropertyPage::OnOK();
  4320.  
  4321.     // never visited this page or no change -- don't bother
  4322.     if(!m_bActivated ||
  4323.        !IS_APPLY_ENABLED(this)){
  4324.         return;
  4325.     }    
  4326.  
  4327.     //EDT_BeginBatchChanges(m_pMWContext);
  4328.  
  4329.     // Set anything in the current Name/Value strings
  4330.     OnVarSet();
  4331.     
  4332.     OkToClose();
  4333.  
  4334.     //EDT_EndBatchChanges(m_pMWContext);
  4335. }
  4336.  
  4337. void CDocMetaPage::DoDataExchange(CDataExchange* pDX)
  4338. {
  4339.     CPropertyPage::DoDataExchange(pDX);
  4340.     //{{AFX_DATA_MAP(CDocMetaPage)
  4341.     //}}AFX_DATA_MAP
  4342. }
  4343.  
  4344. BEGIN_MESSAGE_MAP(CDocMetaPage, CNetscapePropertyPage)
  4345.     //{{AFX_MSG_MAP(CDocMetaPage)
  4346.     ON_LBN_SELCHANGE(IDC_EQUIV_LIST, OnSelchangeEquivList)
  4347.     ON_LBN_SELCHANGE(IDC_META_LIST, OnSelchangeMetaList)
  4348.     ON_BN_CLICKED(IDC_VAR_SET, OnVarSet)
  4349.     ON_BN_CLICKED(IDC_VAR_DELETE, OnVarDelete)
  4350.     ON_BN_CLICKED(IDC_VAR_NEW, OnVarNew)
  4351.     ON_EN_CHANGE(IDC_VAR_NAME, OnChangeVarNameOrValue)
  4352.     ON_EN_CHANGE(IDC_VAR_VALUE, OnChangeVarNameOrValue)
  4353.     ON_LBN_SETFOCUS(IDC_EQUIV_LIST, OnSetfocusEquivList)
  4354.     ON_LBN_SETFOCUS(IDC_META_LIST, OnSetfocusMetaList)
  4355.     //}}AFX_MSG_MAP
  4356. END_MESSAGE_MAP()
  4357.  
  4358.  
  4359. // This needs to match contents of Font Size drop-down listbox
  4360. // 0 = "Default", 1 - 7 = font sizes, 8 = "Don't Change"
  4361. static int iDontChangeFontSizeIndex = 8;
  4362. static int iDontChangeFontColorIndex = 0;
  4363.  
  4364. ///////////////////////////////////////////////////////////////////
  4365. CCharacterPage::CCharacterPage(CWnd* pParent,
  4366.                                MWContext *pMWContext,
  4367.                                CEditorResourceSwitcher * pResourceSwitcher,
  4368.                                EDT_CharacterData *pData)
  4369.     : CNetscapePropertyPage(CCharacterPage::IDD),
  4370.       m_pMWContext(pMWContext),
  4371.       m_pResourceSwitcher(pResourceSwitcher),
  4372.       m_pData(pData),
  4373.       m_bActivated(0),
  4374.       m_pPageData(0),
  4375.       m_crDefault(0),
  4376.       m_bCustomColor(0),
  4377.       m_iNoChangeFontSize(0),
  4378.       m_iNoChangeFontFace(0),
  4379.       m_iOtherIndex(0),
  4380.       m_bMultipleFonts(0),
  4381.       m_bUseDefault(0)
  4382. {
  4383.     //{{AFX_DATA_INIT(CCharacterPage)
  4384.     //}}AFX_DATA_INIT
  4385.     ASSERT(pMWContext);
  4386.     // Could we ever get here and have no data?
  4387.     // We shouldn't, but maybe we shouldn't assume it here
  4388.     //  and just gray all controls if no character data.
  4389.     ASSERT(pData);
  4390.  
  4391. #ifdef XP_WIN32
  4392.     // Set the hInstance so we get template from editor's resource DLL
  4393.     m_psp.hInstance = AfxGetResourceHandle();
  4394. #endif
  4395. }
  4396.  
  4397.  
  4398. void CCharacterPage::DoDataExchange(CDataExchange* pDX)
  4399. {
  4400.     CPropertyPage::DoDataExchange(pDX);
  4401.     //{{AFX_DATA_MAP(CCharacterPage)
  4402.         // NOTE: the ClassWizard will add DDX and DDV calls here
  4403.     //}}AFX_DATA_MAP
  4404. }
  4405.  
  4406. BEGIN_MESSAGE_MAP(CCharacterPage, CNetscapePropertyPage)
  4407.     //{{AFX_MSG_MAP(CCharacterPage)
  4408.     ON_BN_CLICKED(IDC_OVERRIDE_COLOR, EnableApply)
  4409.     ON_BN_CLICKED(IDC_DONT_CHANGE_COLOR, EnableApply)
  4410.     ON_BN_CLICKED(IDC_CHECK_BOLD, EnableApply)
  4411.     ON_BN_CLICKED(IDC_CHECK_ITALIC, EnableApply)
  4412.     ON_BN_CLICKED(IDC_CHECK_UNDERLINE, EnableApply)
  4413.     ON_BN_CLICKED(IDC_CHECK_STRIKETHROUGH, EnableApply)
  4414.     ON_BN_CLICKED(IDC_CHECK_BLINK, EnableApply)
  4415.     ON_BN_CLICKED(IDC_CHECK_NOBREAK, EnableApply)
  4416.     ON_BN_CLICKED(IDC_CHECK_SUBSCRIPT, OnCheckSubscript)
  4417.     ON_BN_CLICKED(IDC_CHECK_SUPERSCRIPT, OnCheckSuperscript)
  4418.     ON_BN_CLICKED(IDC_CLEAR_ALL_STYLES, OnClearAllStyles)
  4419.     ON_BN_CLICKED(IDC_CLEAR_TEXT_STYLES, OnClearTextStyles)
  4420.     ON_CBN_SELCHANGE(IDC_FONT_SIZE_COMBO, OnSelchangeFontSize)
  4421.     ON_CBN_SELCHANGE(IDC_FONT_SIZE_COMBO2, OnSelchangeFontSize)
  4422.     ON_CBN_SELCHANGE(IDC_FONTFACE_COMBO, OnSelchangeFontFace)
  4423.     ON_CBN_EDITCHANGE(IDC_FONTFACE_COMBO, OnChangeFontFace)
  4424.     ON_CBN_EDITCHANGE(IDC_FONT_SIZE_COMBO2, EnableApply)
  4425.     ON_CBN_SELENDOK(IDC_FONTFACE_COMBO, OnSelendokFontFace)
  4426.     ON_BN_CLICKED(IDC_CHOOSE_COLOR, OnChooseColor)
  4427.     ON_WM_CLOSE()
  4428.     //}}AFX_MSG_MAP
  4429. END_MESSAGE_MAP()
  4430. //    ON_BN_CLICKED(IDC_CHOOSE_FONT, OnChooseLocalFont)
  4431.  
  4432. BOOL CCharacterPage::OnSetActive() 
  4433. {
  4434.     if(m_pResourceSwitcher && !m_bActivated){
  4435.         // We must be sure we have switched
  4436.         //  the first time here - before dialog creation
  4437.         m_pResourceSwitcher->switchResources();
  4438.     }
  4439.     if(!CPropertyPage::OnSetActive())
  4440.         return FALSE;
  4441.  
  4442.     if(m_bActivated)
  4443.         return TRUE;
  4444.  
  4445.     // Switch back to EXE's resources
  4446.     if( m_pResourceSwitcher ){
  4447.         m_pResourceSwitcher->Reset();
  4448.     }
  4449.  
  4450.     m_pPageData = EDT_GetPageData(m_pMWContext);
  4451.  
  4452.     if( m_pPageData == NULL ){
  4453.         return FALSE;
  4454.     }
  4455.    
  4456.     // Note: Don't set m_bActivated yet! -- SEE BELOW
  4457.  
  4458.     // Attach color picker button to our color button class
  4459.     if( !m_TextColorButton.Subclass(this, IDC_CHOOSE_COLOR, &m_crColor) ){
  4460.         return FALSE;
  4461.     }
  4462.     
  4463.     // Get the "Default" color used by the Browser
  4464.     COLORREF tmpColor,defColor;
  4465.     XP_Bool bCust;
  4466.     PREF_GetColorPrefDWord("browser.foreground_color",&tmpColor);
  4467.     PREF_GetDefaultColorPrefDWord("browser.foreground_color",&defColor);
  4468.     PREF_GetBoolPref("browser.custom_text_color",&bCust);
  4469.     m_crDefault = bCust ? tmpColor : defColor;
  4470.  
  4471.     // Get current color at cursor or selection
  4472.     m_crColor = WFE_GetCurrentFontColor(m_pMWContext);
  4473.  
  4474.     BOOL bUseColor = TRUE;
  4475.     if( m_crColor == DEFAULT_COLORREF){
  4476.         // Show the default color on the button
  4477.         m_crColor = m_crDefault;
  4478.         m_bUseDefault = TRUE;
  4479.     }
  4480.     if( m_crColor == MIXED_COLORREF ){
  4481.         // Change the text on radio button to: "Don't change (mixed colors)
  4482.         GetDlgItem(IDC_DONT_CHANGE_COLOR)->SetWindowText(szLoadString(IDS_MIXED_COLORS));
  4483.         ((CButton*)GetDlgItem(IDC_DONT_CHANGE_COLOR))->SetCheck(1);
  4484.     } else {
  4485.         ((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->SetCheck(1);
  4486.     }
  4487.     
  4488.     // Attach CNSComboBox class to existing control to do user-drawing
  4489.     if( !m_FontFaceCombo.Subclass(this, IDC_FONTFACE_COMBO) ){
  4490.         return FALSE;
  4491.     }
  4492.     
  4493.     // Fill the combobox with global lists of fonts (MUST BE STATIC STRINGS!)
  4494.     // This will add "Other..." at bottom of list only if too many fonts are installed
  4495.     m_iOtherIndex = wfe_FillFontComboBox(&m_FontFaceCombo);
  4496.  
  4497.     // Get current font face and index to it in font list
  4498.     char * pFace = EDT_GetFontFace(m_pMWContext);
  4499.     int iFontIndex = m_FontFaceCombo.FindSelectedOrSetText(pFace);
  4500.     
  4501.     // Save whether or not we have mulitple fonts at startup
  4502.     m_bMultipleFonts = (pFace == NULL);
  4503.     char * pNoChangeText = m_bMultipleFonts ? ed_pMixedFonts : ed_pDontChange;
  4504.     // Add the "Dont Change" item at the bottom
  4505.     m_iNoChangeFontFace = m_FontFaceCombo.AddString(pNoChangeText);
  4506.     
  4507.     // Set the message explaining the font after selecting it in listbox
  4508.     SetFontFaceMessage(iFontIndex);
  4509.  
  4510.     // We need to rebuild font size display if font face changes from
  4511.     //   Variable to Fixed Width or vice versa, so monitor state
  4512.     m_bFixedWidth = (iFontIndex == 1);
  4513.  
  4514.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_BOLD)),TF_BOLD);
  4515.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_ITALIC)), TF_ITALIC);
  4516.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_UNDERLINE)), TF_UNDERLINE);
  4517.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_STRIKETHROUGH)), TF_STRIKEOUT);
  4518.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT)), TF_SUPER);
  4519.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT)), TF_SUB); 
  4520.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_BLINK)), TF_BLINK);      
  4521.     InitCheckbox(((CButton*)GetDlgItem(IDC_CHECK_NOBREAK)), TF_NOBREAK); 
  4522.  
  4523.     // We have 2 comboboxes: 1 droplist for regular (relative size) mode,
  4524.     //   and combobox with edit style for advanced mode
  4525.     if( !m_FontSizeCombo.Subclass(this, wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ? 
  4526.                                         IDC_FONT_SIZE_COMBO2 : IDC_FONT_SIZE_COMBO) ){
  4527.         return FALSE;
  4528.     }
  4529.     // Hide the combobox we will not use
  4530.     GetDlgItem(wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ? IDC_FONT_SIZE_COMBO : IDC_FONT_SIZE_COMBO2)->ShowWindow(SW_HIDE);
  4531.  
  4532.  
  4533.     // Fill Font Size combo. 3rd param is TRUE if font face = Fixed Width
  4534.     wfe_FillFontSizeCombo(m_pMWContext, &m_FontSizeCombo, m_bFixedWidth);
  4535.  
  4536.     // Add the "Dont Change" item at the bottom
  4537.     m_iNoChangeFontSize = m_FontSizeCombo.AddString(ed_pDontChange);
  4538.  
  4539.     // Change message to that describing advanced mode
  4540.     if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ){
  4541.         GetDlgItem(IDC_FONT_SIZE_MSG)->SetWindowText(szLoadString(IDS_ADVANCED_FONTSIZE_MSG));
  4542.     }
  4543.  
  4544.     // Set FontSize combobox selected
  4545.     int iSel = -1;
  4546.     if( m_pData->mask & TF_FONT_SIZE ){
  4547.         // If no size, use default instead
  4548.         iSel =  m_pData->iSize ? m_pData->iSize - 1 : 2;
  4549.         m_FontSizeCombo.SetCurSel(iSel);
  4550.         // Weird -- we must set string manually
  4551.         char * pSelected = (char*)m_FontSizeCombo.GetItemData(iSel);
  4552.         if( *pSelected == '_'){
  4553.             pSelected++;
  4554.         }
  4555.         m_FontSizeCombo.SetWindowText(pSelected);
  4556.     } else if( (m_pData->mask & TF_FONT_POINT_SIZE) && m_pData->iPointSize ){
  4557.         char pSize[16];
  4558.         wsprintf(pSize, "%d", m_pData->iPointSize);
  4559.         m_FontSizeCombo.FindSelectedOrSetText(pSize, MAX_FONT_SIZE);
  4560.     }
  4561.  
  4562.     // We set this last because initialization
  4563.     //  uses it to know first-time through
  4564.     m_bActivated = TRUE;
  4565.  
  4566.     // Send data to controls
  4567.     UpdateData(FALSE);
  4568.     return(TRUE);
  4569. }
  4570.  
  4571. void CCharacterPage::OnHelp() 
  4572. {
  4573.     NetHelp(HELP_PROPS_CHARACTER);
  4574. }
  4575.  
  4576. BOOL CCharacterPage::OnKillActive()
  4577.  
  4578. {
  4579.     if( ! GetAndValidateFontSizes() ){
  4580.         return FALSE;
  4581.     }
  4582.     // Contrary to MFC help, this does NOT call our OnOK
  4583.     return CPropertyPage::OnKillActive();
  4584. }
  4585.  
  4586. BOOL CCharacterPage::GetAndValidateFontSizes()
  4587. {
  4588.     int iSel = m_FontSizeCombo.GetCurSel();
  4589.     if( iSel == iDontChangeFontSizeIndex ||
  4590.         (iSel == -1 && wfe_iFontSizeMode != ED_FONTSIZE_ADVANCED) ){
  4591.         // Ignore this attribute
  4592.         FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
  4593.         return TRUE;
  4594.     }
  4595.     if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED){
  4596.         CString csAbsoluteSize;
  4597.         m_FontSizeCombo.GetWindowText(csAbsoluteSize);
  4598.         csAbsoluteSize.TrimLeft();
  4599.         csAbsoluteSize.TrimRight();
  4600.  
  4601.         // Empty is OK - same as "Don't change"
  4602.         // So get the Relative size 
  4603.         if( csAbsoluteSize.IsEmpty() ){
  4604.             // We may be ignore this attribute if no
  4605.             //  relative size is selected
  4606.             FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
  4607.             m_pData->iPointSize = 0;
  4608.         } else if( iSel == -1 || iSel >= MAX_FONT_SIZE ){
  4609.             char* pEnd;
  4610.             int32 iSize = (int)strtol( LPCSTR(csAbsoluteSize), &pEnd, 10 );
  4611.             // Bad conversion if end pointer isn't at terminal null;
  4612.             if( *pEnd != '\0' ||
  4613.                 iSize < MIN_FONT_SIZE_RELATIVE ||
  4614.                 iSize > ED_FONT_POINT_SIZE_MAX ){
  4615.         
  4616.                 char szMessage[256];
  4617.                 // Construct a string showing correct range
  4618.                 wsprintf( szMessage, szLoadString(IDS_INTEGER_RANGE_ERROR),
  4619.                           ED_FONT_POINT_SIZE_MIN, ED_FONT_POINT_SIZE_MAX );
  4620.  
  4621.                 // Notify user with similar message to the DDV_ validation system
  4622.                 MessageBox(szMessage, szLoadString(AFX_IDS_APP_TITLE), MB_ICONEXCLAMATION | MB_OK);
  4623.                 return FALSE;
  4624.             }
  4625.             if( iSize >= MIN_FONT_SIZE_RELATIVE && iSize <= 4 ){
  4626.                 // Assume they really wanted the Relative scale
  4627.                 iSel = iSize + 3;
  4628.                 m_pData->iPointSize = 0;
  4629.             } else {
  4630.                 // Size is OK - store it
  4631.                 m_pData->iPointSize = (int16)iSize;
  4632.  
  4633.                 // Set bit mask to indicate we want PointSize, not HTML relative size
  4634.                 FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
  4635.                 FE_SET_BIT(m_pData->mask, TF_FONT_POINT_SIZE);
  4636.                 FE_SET_BIT(m_pData->values, TF_FONT_POINT_SIZE);
  4637.                 m_pData->iPointSize = (int16)iSize;
  4638.             }
  4639.         }
  4640.     }
  4641.  
  4642.     if( m_pData->iPointSize == 0){
  4643.         if( m_iNoChangeFontSize > 0 && iSel == m_iNoChangeFontSize ){
  4644.             // Clear the bit so we will ignore this attribute
  4645.             FE_CLEAR_BIT(m_pData->mask, TF_FONT_SIZE);
  4646.         } else if( iSel >= 0 && iSel < MAX_FONT_SIZE ){
  4647.             // Set the size to the designated value - XP handles default
  4648.             // (3rd item = "default", i.e., no SIZE param written)
  4649.             FE_SET_BIT(m_pData->mask, TF_FONT_SIZE);
  4650.             FE_SET_BIT(m_pData->values, TF_FONT_SIZE);
  4651.             m_pData->iSize = iSel+1;
  4652.         }
  4653.     }
  4654.     return TRUE;
  4655. }
  4656.  
  4657. void CCharacterPage::OnOK() 
  4658. {
  4659.     CPropertyPage::OnOK();
  4660.  
  4661.     // never visited this page or no change -- don't bother
  4662.     if(!m_bActivated ||
  4663.        !IS_APPLY_ENABLED(this)){
  4664.         return;
  4665.     }    
  4666.     
  4667.     //EDT_BeginBatchChanges(m_pMWContext);
  4668.     if( !GetAndValidateFontSizes() ){
  4669.         return;
  4670.     }
  4671.  
  4672.     // Set color if checkbox is checked
  4673.     if( ((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->GetCheck() ){
  4674.         if( m_bUseDefault ){
  4675.             // Set the color to the default size by
  4676.             //  setting mask bit and clearing value
  4677.             FE_SET_BIT(m_pData->mask, TF_FONT_COLOR);
  4678.             FE_CLEAR_BIT(m_pData->values, TF_FONT_COLOR);
  4679.         } else {
  4680.             // Set the color to the designated value
  4681.             FE_SET_BIT(m_pData->mask, TF_FONT_COLOR);
  4682.             FE_SET_BIT(m_pData->values, TF_FONT_COLOR);
  4683.             WFE_SetLO_ColorPtr( m_crColor, &m_pData->pColor );
  4684.         }
  4685.     } else {
  4686.         // Ignore this attribute
  4687.         FE_CLEAR_BIT(m_pData->mask, TF_FONT_COLOR);
  4688.     }
  4689.      
  4690.     int iSel = m_FontFaceCombo.GetCurSel();
  4691.     CString csFace;
  4692.     char * pNewFace = NULL;
  4693.     if( iSel == -1 ){
  4694.         m_FontFaceCombo.GetWindowText(csFace);
  4695.         csFace.TrimLeft();
  4696.         csFace.TrimRight();
  4697.         if( !csFace.IsEmpty() ){
  4698.             // We have a local font name
  4699.             pNewFace = (char*)LPCSTR(csFace);
  4700.             FE_SET_BIT(m_pData->mask, TF_FONT_FACE);
  4701.         }
  4702.     } else if( m_iNoChangeFontFace > 0 && iSel == m_iNoChangeFontFace ){
  4703.         // Clear the bit so we will ignore this attribute
  4704.         FE_CLEAR_BIT(m_pData->mask, TF_FONT_FACE);
  4705.     } else {
  4706.         // We may be sure of the font and its in our list
  4707.         //  (EDT_SetFontFace will set default variable or fixed width 
  4708.         //   correctly using the supplied "font face" string
  4709.         FE_SET_BIT(m_pData->mask, TF_FONT_FACE);
  4710.         // Get pointer to fontface string in combobox
  4711.         pNewFace = (char*)m_FontFaceCombo.GetItemData(iSel);
  4712.     }
  4713.     // Set the bits in our data struct
  4714.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_BOLD)), TF_BOLD);
  4715.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_ITALIC)), TF_ITALIC);
  4716.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_UNDERLINE)), TF_UNDERLINE);
  4717.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_STRIKETHROUGH)), TF_STRIKEOUT);
  4718.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT)), TF_SUPER);
  4719.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT)), TF_SUB);
  4720.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_BLINK)), TF_BLINK);
  4721.     SetCharacterStyle(((CButton*)GetDlgItem(IDC_CHECK_NOBREAK)), TF_NOBREAK);
  4722.  
  4723.     // Set font face in the supplied struct and set all character data
  4724.     EDT_SetFontFace(m_pMWContext, m_pData, iSel, pNewFace);
  4725.  
  4726.     OkToClose();
  4727.     //EDT_EndBatchChanges(m_pMWContext);
  4728. }
  4729.  
  4730. void CCharacterPage::InitCheckbox(CButton *pButton, ED_TextFormat tf)
  4731. {
  4732.     // Get current style but clear all relevant button-style bits
  4733.     UINT nStyle = CASTUINT(pButton->GetButtonStyle() & 0xFFFFFFF0L);
  4734.  
  4735.     if( m_pData->mask & tf ) {
  4736.         // We know the style, so we can use 2-state boxes
  4737.         nStyle |= BS_AUTOCHECKBOX;
  4738.     } else {
  4739.         // We don't know the style, so we use 3-state boxes
  4740.         //  so user can return to the "don't change" state
  4741.         nStyle |= BS_AUTO3STATE;
  4742.     }
  4743.     pButton->SetButtonStyle(nStyle);
  4744.     SetCheck(pButton, tf);
  4745. }
  4746.  
  4747. int CCharacterPage::SetCheck(CButton *pButton, ED_TextFormat tf)
  4748. {
  4749.     int iCheck = 2; // Uncertain/mixed state
  4750.     if( m_pData->mask & tf){ 
  4751.         iCheck = (m_pData->values & tf) ? 1 : 0;
  4752.     }
  4753.     pButton->SetCheck(iCheck);
  4754.     return iCheck;
  4755. }
  4756.  
  4757. void CCharacterPage::SetCharacterStyle(CButton *pButton, ED_TextFormat tf)
  4758. {
  4759.     int iCheck = pButton->GetCheck();
  4760.     
  4761.     if( iCheck == 2 ){
  4762.         // Don't change this style - clear mask bit
  4763.         FE_CLEAR_BIT(m_pData->mask,tf);
  4764.     } else {
  4765.         // Set the style -- set mask bit
  4766.         FE_SET_BIT(m_pData->mask, tf);
  4767.     }
  4768.  
  4769.     if( iCheck == 1){
  4770.         // Set the value bit
  4771.         FE_SET_BIT(m_pData->values,tf);
  4772.     } else {
  4773.         FE_CLEAR_BIT(m_pData->values,tf);
  4774.     }
  4775. }
  4776.  
  4777. void CCharacterPage::OnChooseLocalFont()
  4778. {
  4779.     CFontDialog dlg(NULL, CF_SCREENFONTS | CF_TTONLY, NULL, this);
  4780.     if( dlg.DoModal() ){
  4781.         CString csNewFont = dlg.GetFaceName();
  4782.         m_FontFaceCombo.SetWindowText(LPCSTR(csNewFont));
  4783.         GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText(szLoadString(IDS_TRUE_TYPE));
  4784.         SetModified(TRUE);
  4785.     }
  4786. }
  4787.  
  4788. void CCharacterPage::OnChooseColor() 
  4789. {
  4790.     // Get the combobox location so we popup new dialog just under it
  4791.     RECT rect;
  4792.     GetDlgItem(IDC_CHOOSE_COLOR)->GetWindowRect(&rect);
  4793.  
  4794.     CColorPicker ColorPicker(this, m_pMWContext, m_crColor, DEFAULT_COLORREF, 0, &rect);
  4795.     COLORREF crNew = ColorPicker.GetColor();
  4796.  
  4797.     if( crNew != CANCEL_COLORREF ){
  4798.         if( crNew == DEFAULT_COLORREF ){
  4799.             m_crColor = m_crDefault;
  4800.             m_bUseDefault = TRUE;
  4801.         } else {
  4802.             m_crColor = crNew;
  4803.             m_bUseDefault = FALSE;
  4804.         }
  4805.         // Refresh color button
  4806.         m_TextColorButton.Update();
  4807.         // Set radio buttons to show "Use color"
  4808.         ((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->SetCheck(1);
  4809.         ((CButton*)GetDlgItem(IDC_DONT_CHANGE_COLOR))->SetCheck(0);
  4810.         SetModified(TRUE);
  4811.     }
  4812. }
  4813.  
  4814. void CCharacterPage::EnableApply() 
  4815. {
  4816.     SetModified(TRUE);
  4817. }
  4818.  
  4819. void CCharacterPage::OnCheckSubscript() 
  4820. {
  4821.     // Super and Sub are mutually exclusive
  4822.     // Problem: This wipes out mixed-state items!
  4823.     if( ((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT))->GetCheck() == 1 ){
  4824.         ((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT))->SetCheck(0);
  4825.     }
  4826.     SetModified(TRUE);
  4827. }
  4828.  
  4829. void CCharacterPage::OnCheckSuperscript() 
  4830. {
  4831.     // Super and Sub are mutually exclusive
  4832.     // Problem: This wipes out mixed-state items!
  4833.     if( ((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT))->GetCheck() == 1 ){
  4834.         ((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT))->SetCheck(0);
  4835.     }
  4836.     SetModified(TRUE);
  4837. }
  4838.  
  4839. // Next 2 don't change the doc, 
  4840. //  just change the control states
  4841. void CCharacterPage::OnClearAllStyles() 
  4842. {
  4843.     // Remove all styles in the controls
  4844.     
  4845.     // Set to the "default" font size
  4846.     m_FontSizeCombo.SetCurSel(2);
  4847.     // Update the display
  4848.     OnSelchangeFontSize();
  4849.  
  4850.     // Set to default color
  4851.     m_bUseDefault = TRUE;
  4852.     m_crColor = m_crDefault;
  4853.     m_TextColorButton.Update();
  4854.  
  4855.     ((CButton*)GetDlgItem(IDC_DONT_CHANGE_COLOR))->SetCheck(0);
  4856.     ((CButton*)GetDlgItem(IDC_OVERRIDE_COLOR))->SetCheck(1);
  4857.    
  4858.     // Set to default variable font face
  4859.     m_FontFaceCombo.SetCurSel(0);
  4860.     OnSelchangeFontFace();
  4861.     
  4862.     OnClearTextStyles();
  4863. }
  4864.  
  4865. void CCharacterPage::OnClearTextStyles() 
  4866. {
  4867.     ((CButton*)GetDlgItem(IDC_CHECK_BOLD))->SetCheck(0);
  4868.     ((CButton*)GetDlgItem(IDC_CHECK_ITALIC))->SetCheck(0);
  4869.     ((CButton*)GetDlgItem(IDC_CHECK_UNDERLINE))->SetCheck(0);
  4870.     ((CButton*)GetDlgItem(IDC_CHECK_STRIKETHROUGH))->SetCheck(0);
  4871.     ((CButton*)GetDlgItem(IDC_CHECK_SUPERSCRIPT))->SetCheck(0);
  4872.     ((CButton*)GetDlgItem(IDC_CHECK_SUBSCRIPT))->SetCheck(0);
  4873.     ((CButton*)GetDlgItem(IDC_CHECK_BLINK))->SetCheck(0);
  4874.     ((CButton*)GetDlgItem(IDC_CHECK_NOBREAK))->SetCheck(0);
  4875.     SetModified(TRUE);
  4876. }
  4877.  
  4878. void CCharacterPage::OnChangeFontFace() 
  4879. {
  4880.     GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText("");
  4881.     SetModified(TRUE);
  4882.     // Do any autosearch here?
  4883. }
  4884.  
  4885. void CCharacterPage::SetFontFaceMessage(int iSel)
  4886. {
  4887.     UINT nID;
  4888.     if( iSel == -1 || 
  4889.         (iSel == m_iNoChangeFontFace && !m_bMultipleFonts) ||
  4890.         (m_iOtherIndex && iSel == m_iOtherIndex) ){
  4891.         GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText("");
  4892.         return;
  4893.     }
  4894.     if( iSel == m_iNoChangeFontFace ){
  4895.         nID = IDS_MULTIPLE_FONTS;
  4896.     } else if( iSel == 0){
  4897.         nID = IDS_DEFAULT_VARIABLE;
  4898.     } else if ( iSel == 1 ){
  4899.         nID = IDS_DEFAULT_FIXED_WIDTH;
  4900.     } else { 
  4901.         char * pFace = (char*)m_FontFaceCombo.GetItemData(iSel);
  4902.         // Give a different message if we find an "XP" font face
  4903.         if( pFace != EDT_TranslateToXPFontFace(pFace) ){
  4904.             nID = IDS_XP_FONT;
  4905.         } else {
  4906.             nID = IDS_LOCAL_FONT;
  4907.         }
  4908.     }
  4909.     GetDlgItem(IDC_FONTFACE_MSG)->SetWindowText(szLoadString(nID));
  4910. }
  4911.  
  4912. void CCharacterPage::OnSelchangeFontFace() 
  4913. {
  4914.     int iSel = m_FontFaceCombo.GetCurSel();
  4915.     if( m_iOtherIndex && iSel == m_iOtherIndex ){
  4916.         m_FontFaceCombo.SetCurSel(-1);
  4917.         iSel = -1;
  4918.     }
  4919.     if( iSel >= 0 ){
  4920.         char * pSelected = (char*)m_FontFaceCombo.GetItemData(iSel);
  4921.         if( *pSelected == '_'){
  4922.             pSelected++;
  4923.         }
  4924.         m_FontFaceCombo.SetWindowText(pSelected);
  4925.     }
  4926.     // Rebuild font size list if changing from variable to fixed width or vice versa
  4927.     if( m_bFixedWidth != (iSel == 1) ){
  4928.         m_bFixedWidth = (iSel == 1);
  4929.         wfe_FillFontSizeCombo(m_pMWContext, &m_FontSizeCombo, m_bFixedWidth);
  4930.     }
  4931.     SetFontFaceMessage(iSel);
  4932.     SetModified(TRUE);
  4933. }
  4934.  
  4935. void CCharacterPage::OnSelendokFontFace()
  4936. {
  4937.     int iSel = m_FontFaceCombo.GetCurSel();
  4938.     if( m_iOtherIndex &&
  4939.         iSel == m_iOtherIndex ){
  4940.         m_FontFaceCombo.SetCurSel(-1);
  4941.         OnChooseLocalFont();
  4942.         return;
  4943.     }
  4944. }
  4945.  
  4946. void CCharacterPage::OnSelchangeFontSize() 
  4947. {
  4948.     // User can use the last item to not change any sizes,
  4949.     //  but it looks better to show blank combobox field
  4950.     int iSel = m_FontSizeCombo.GetCurSel();
  4951.     if( iSel == iDontChangeFontSizeIndex ){
  4952.         m_FontSizeCombo.SetCurSel(-1);
  4953.     }
  4954.     if( wfe_iFontSizeMode == ED_FONTSIZE_ADVANCED ){
  4955.         // We must set text manually in edit box
  4956.         if( iSel >= 0 ){
  4957.             char * pSelected = (char*)m_FontSizeCombo.GetItemData(iSel);
  4958.             if( *pSelected == '_'){
  4959.                 pSelected++;
  4960.             }
  4961.             m_FontSizeCombo.SetWindowText(pSelected);
  4962.         } else {
  4963.             m_FontSizeCombo.SetWindowText("");
  4964.         }
  4965.     } else {
  4966.         m_pData->iPointSize = 0;
  4967.     }
  4968.     SetModified(TRUE);
  4969. }
  4970.  
  4971. void CCharacterPage::OnClose() 
  4972. {
  4973.     // Free extra data we allocated
  4974.     if( m_pPageData    ){
  4975.         EDT_FreePageData(m_pPageData);
  4976.     }
  4977.     CNetscapePropertyPage::OnClose();
  4978. }
  4979.  
  4980. ///////////////////////////////////////////////////////////////////
  4981. /*
  4982. // For quick reference:
  4983. typedef enum {
  4984.     ED_LIST_TYPE_DEFAULT,
  4985.     ED_LIST_TYPE_DIGIT,         
  4986.     ED_LIST_TYPE_ROMAN,
  4987.     ED_LIST_TYPE_BIG_LETTERS,
  4988.     ED_LIST_TYPE_SMALL_LETTERS,
  4989.     ED_LIST_TYPE_CIRCLE,
  4990.     ED_LIST_TYPE_SQUARE,
  4991.     ED_LIST_TYPE_DISC,
  4992. } ED_ListType;
  4993.  
  4994.  
  4995. struct _EDT_ListData {
  4996.     intn iTagType;         P_UNUM_LIST, P_NUM_LIST, P_BLOCKQUOTE
  4997.                            P_DIRECTORY, P_MENU, P_DESC_LIST
  4998.     Bool bCompact;
  4999.     ED_ListType eType;
  5000.     int iStart;            automatically maps, start is 1
  5001. };
  5002. */
  5003.  
  5004. //Container styles:
  5005. enum {
  5006.     ED_NO_CONTAINER,
  5007.     ED_LIST,
  5008.     ED_BLOCKQUOTE
  5009. };
  5010.  
  5011.  
  5012. // List Styles
  5013. enum {
  5014.     ED_UNUM_LIST,
  5015.     ED_NUM_LIST,
  5016.     ED_DIR_LIST,
  5017.     ED_MENU_LIST,
  5018.     ED_DESC_LIST
  5019. };
  5020.  
  5021.  
  5022. //Numbered List Item styles
  5023. enum {
  5024.     ED_AUTOMATIC,
  5025.     ED_DIGIT,
  5026.     ED_BIG_ROMAN,
  5027.     ED_SMALL_ROMAN,
  5028.     ED_BIG_LETTERS,
  5029.     ED_SMALL_LETTERS
  5030. };
  5031.  
  5032. //Unumbered List Item styles
  5033. enum {
  5034.     ED_SOLID_CIRCLE = 1, // We share     ED_AUTOMATIC,
  5035.     ED_OPEN_CIRCLE,
  5036.     ED_SOLID_SQUARE
  5037. };
  5038.  
  5039. #define ED_DEFAULT     -1
  5040.  
  5041. // This is in edframe.cpp. Its the tag types that map
  5042. //  onto the listbox index, just as in the paragraph format toolbar
  5043. extern TagType FEED_nParagraphTags[];
  5044.  
  5045. // Fixed index values for Paragraph tags list
  5046. #define ED_PARA_NORMAL     0
  5047. #define ED_PARA_LIST       9
  5048. #define ED_PARA_DESC_TITLE 10
  5049. #define ED_PARA_DESC_TEXT  11
  5050.  
  5051. /////////////////////////////////////////
  5052. // Paragraph / Lists / Alignment
  5053. //
  5054. CParagraphPage::CParagraphPage(CWnd* pParent, MWContext * pMWContext,
  5055.                                CEditorResourceSwitcher * pResourceSwitcher)
  5056.     : CNetscapePropertyPage(CParagraphPage::IDD),
  5057.       m_pMWContext(pMWContext),
  5058.       m_pResourceSwitcher(pResourceSwitcher),
  5059.       m_pListData(NULL),
  5060.       m_bActivated(0),
  5061.       m_Align(ED_ALIGN_LEFT),
  5062.       m_iParagraphStyle(0),
  5063.       m_iContainerStyle(0),
  5064.       m_iListStyle(-1),
  5065.       m_iBulletStyle(0),
  5066.       m_iNumberStyle(0),
  5067.       m_iMixedStyle(0)
  5068. {
  5069.     //{{AFX_DATA_INIT(CParagraphPage)
  5070.     m_iStartNumber = 1;
  5071.     m_bCompact = FALSE;
  5072.     //}}AFX_DATA_INIT
  5073.     ASSERT(pMWContext);
  5074.  
  5075. #ifdef XP_WIN32
  5076.     // Set the hInstance so we get template from editor's resource DLL
  5077.     m_psp.hInstance = AfxGetResourceHandle();
  5078. #endif
  5079. }
  5080.  
  5081.  
  5082. void CParagraphPage::DoDataExchange(CDataExchange* pDX)
  5083. {
  5084.     CPropertyPage::DoDataExchange(pDX);
  5085.     //{{AFX_DATA_MAP(CParagraphPage)
  5086.     DDX_Text(pDX, IDC_LIST_START_NUMBER, m_iStartNumber);
  5087.     DDV_MinMaxInt(pDX, m_iStartNumber, 1, 10000);
  5088.     DDX_Check(pDX, IDC_COMPACT_LIST, m_bCompact);
  5089.     //}}AFX_DATA_MAP
  5090. }
  5091.  
  5092. BEGIN_MESSAGE_MAP(CParagraphPage, CNetscapePropertyPage)
  5093.     //{{AFX_MSG_MAP(CParagraphPage)
  5094.     ON_BN_CLICKED(IDC_ALIGN_CENTER, OnAlignCenter)
  5095.     ON_BN_CLICKED(IDC_ALIGN_LEFT, OnAlignLeft)
  5096.     ON_BN_CLICKED(IDC_ALIGN_RIGHT, OnAlignRight)
  5097.     ON_CBN_SELCHANGE(IDC_CONTAINER_STYLES, OnSelchangeContainerStyle)
  5098.     ON_CBN_SELCHANGE(IDC_LIST_ITEM_STYLES, OnSelchangeListItemStyle)
  5099.     ON_EN_CHANGE(IDC_LIST_START_NUMBER, OnChangeListStartNumber)
  5100.     ON_CBN_SELCHANGE(IDC_LIST_STYLES, OnSelchangeListStyles)
  5101.     ON_CBN_SELCHANGE(IDC_PARAGRAPH_STYLES, OnSelchangeParagraphStyles)
  5102.     ON_WM_CLOSE()
  5103.     //}}AFX_MSG_MAP
  5104. END_MESSAGE_MAP()
  5105.  
  5106.  
  5107. BOOL CParagraphPage::OnSetActive() 
  5108. {
  5109.     int i;
  5110.     if(m_pResourceSwitcher && !m_bActivated){
  5111.         // We must be sure we have switched
  5112.         //  the first time here - before dialog creation
  5113.         m_pResourceSwitcher->switchResources();
  5114.     }
  5115.     if(!CPropertyPage::OnSetActive())
  5116.         return(FALSE);
  5117.  
  5118.     if(m_bActivated)
  5119.         return(TRUE);
  5120.  
  5121.  
  5122.     // Switch back to EXE's resources
  5123.     if( m_pResourceSwitcher ){
  5124.         m_pResourceSwitcher->Reset();
  5125.     }
  5126.  
  5127.     m_bActivated = TRUE;
  5128.     CComboBox * pContainerStyles;
  5129.     CComboBox * pListStyles;
  5130.  
  5131.     // Initialize alignment param and radio buttons
  5132.     m_Align = EDT_GetParagraphAlign( m_pMWContext );
  5133.  
  5134.     switch (m_Align) {
  5135.         case ED_ALIGN_CENTER:
  5136.         case ED_ALIGN_ABSCENTER:
  5137.             ((CButton*)GetDlgItem(IDC_ALIGN_CENTER))->SetCheck(1);
  5138.             break;
  5139.         case ED_ALIGN_RIGHT:
  5140.             ((CButton*)GetDlgItem(IDC_ALIGN_RIGHT))->SetCheck(1);
  5141.             break;
  5142.         default:
  5143.             ((CButton*)GetDlgItem(IDC_ALIGN_LEFT))->SetCheck(1);
  5144.             // We end up here for ED_ALIGN_DEFAULT as well as ED_ALIGN_LEFT
  5145.             m_Align = ED_ALIGN_LEFT;    
  5146.             break;
  5147.     }
  5148.  
  5149.     CComboBox *pParagraphStyles = (CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES);
  5150.     
  5151.     m_ParagraphFormat = EDT_GetParagraphFormatting(m_pMWContext);
  5152.     //Try to get Container data
  5153.     // (We can't do this just for list because we may be
  5154.     //  a block quote, which may have any paragraph style)
  5155.     m_pListData = EDT_GetListData(m_pMWContext);
  5156.  
  5157.     // Fill the Paragraph styles list:    
  5158.     for ( i = 0; FEED_nParagraphTags[i] != P_UNKNOWN; i++ ){
  5159.         // Major KLUDGE: We want "Description List" to appear in Toolbar Combobox,
  5160.         //   but not in this combobox - we put it in List Styles combo instead
  5161. //        if( FEED_nParagraphTags[i] != P_DESC_LIST)
  5162.             pParagraphStyles->AddString(szLoadString(
  5163.                                     CASTUINT(ID_LIST_TEXT_PARAGRAPH_BASE+FEED_nParagraphTags[i])));
  5164.     }
  5165.     // We will add another item at end to allow user to see
  5166.     // "Mixed (don't change)" in listbox
  5167.     m_iMixedStyle = i;
  5168.  
  5169.     // Figure out the Paragraph style:
  5170.     if( m_ParagraphFormat == P_UNKNOWN ){
  5171.         m_iParagraphStyle = m_iMixedStyle;
  5172.         pParagraphStyles->AddString(szLoadString(IDS_MIXED_STYLE));
  5173.     } 
  5174.     else for( i = 0; FEED_nParagraphTags[i] != P_UNKNOWN; i++ ){
  5175.         if( FEED_nParagraphTags[i] == m_ParagraphFormat ){
  5176.             m_iParagraphStyle = i;
  5177.             break;
  5178.         }
  5179.     }
  5180.  
  5181.     if( m_pListData ) {
  5182.         m_iContainerStyle = ED_LIST;
  5183.         switch( m_pListData->iTagType ){
  5184.             case P_UNUM_LIST:
  5185.                 m_iListStyle = ED_UNUM_LIST;
  5186.                 break;
  5187.             case P_NUM_LIST:
  5188.                 m_iListStyle = ED_NUM_LIST;
  5189.                 m_iStartNumber = CASTINT(m_pListData->iStart);
  5190.                 break;
  5191.             case P_BLOCKQUOTE:
  5192.                 m_iContainerStyle = ED_BLOCKQUOTE;
  5193.                 m_iListStyle = ED_DEFAULT;
  5194.                 break;
  5195.             case P_DIRECTORY:
  5196.                 m_iListStyle = ED_DIR_LIST;
  5197.                 break;
  5198.             case P_MENU:
  5199.                 m_iListStyle = ED_MENU_LIST;
  5200.                 break;
  5201.             case P_DESC_LIST:
  5202.                 m_iListStyle = ED_DESC_LIST;
  5203.                 break;
  5204.         }
  5205.  
  5206.         m_iBulletStyle = m_iNumberStyle = ED_DEFAULT;
  5207.         switch( m_pListData->eType ){
  5208.             case ED_LIST_TYPE_DIGIT:         
  5209.                 m_iNumberStyle = ED_DIGIT;
  5210.                 break;
  5211.             case ED_LIST_TYPE_BIG_ROMAN:
  5212.                 m_iNumberStyle = ED_BIG_ROMAN;
  5213.                 break;
  5214.             case ED_LIST_TYPE_SMALL_ROMAN:
  5215.                 m_iNumberStyle = ED_SMALL_ROMAN;
  5216.                 break;
  5217.             case ED_LIST_TYPE_BIG_LETTERS:
  5218.                 m_iNumberStyle = ED_BIG_LETTERS;
  5219.                 break;
  5220.             case ED_LIST_TYPE_SMALL_LETTERS:
  5221.                 m_iNumberStyle = ED_SMALL_LETTERS;
  5222.                 break;
  5223.             case ED_LIST_TYPE_DISC:
  5224.                 m_iBulletStyle = ED_SOLID_CIRCLE;
  5225.                 break;
  5226.             case ED_LIST_TYPE_CIRCLE:
  5227.                 m_iBulletStyle = ED_OPEN_CIRCLE;
  5228.                 break;
  5229.             case ED_LIST_TYPE_SQUARE:
  5230.                 m_iBulletStyle = ED_SOLID_SQUARE;
  5231.                 break;
  5232.         }
  5233.         m_bCompact = m_pListData->bCompact;
  5234.     } else {
  5235.         m_iContainerStyle = ED_NO_CONTAINER;
  5236.     }
  5237.  
  5238.  
  5239.     VERIFY(pContainerStyles = (CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES));
  5240.     VERIFY(pListStyles = (CComboBox*)GetDlgItem(IDC_LIST_STYLES));
  5241.  
  5242.     // Fill the Container styles list
  5243.     pContainerStyles->AddString(szLoadString(IDS_DEFAULT));
  5244.     pContainerStyles->AddString(szLoadString(IDS_LIST));
  5245.     pContainerStyles->AddString(szLoadString(IDS_BLOCK_QUOTE));
  5246.     
  5247.     
  5248.     // Fill the List styles list
  5249.     pListStyles->AddString(szLoadString(IDS_UNUM_LIST));
  5250.     pListStyles->AddString(szLoadString(IDS_NUM_LIST));
  5251.     pListStyles->AddString(szLoadString(IDS_DIRECTORY_LIST));
  5252.     pListStyles->AddString(szLoadString(IDS_MENU_LIST));
  5253.     pListStyles->AddString(szLoadString(IDS_DESCRIPTION_LIST));
  5254.  
  5255.     // Remove/rebuild item styles depending on current state
  5256.     UpdateLists();
  5257.  
  5258.     // TODO - How to get current alignment?
  5259.     //        (Set align radio button to this value)
  5260.  
  5261.     // Send data to controls
  5262.     UpdateData(FALSE);
  5263.     return(TRUE);
  5264. }
  5265.  
  5266. void CParagraphPage::OnHelp() 
  5267. {
  5268.     NetHelp(HELP_PROPS_PARAGRAPH);
  5269. }
  5270.  
  5271. void CParagraphPage::OnOK() 
  5272. {
  5273.     CPropertyPage::OnOK();
  5274.  
  5275.     // never visited this page or no change -- don't bother
  5276.     if(!m_bActivated ||
  5277.        !IS_APPLY_ENABLED(this)){
  5278.         return;
  5279.     }    
  5280.  
  5281.     //EDT_BeginBatchChanges(m_pMWContext);
  5282.  
  5283.     m_iParagraphStyle = ((CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES))->GetCurSel();
  5284.     m_iContainerStyle = ((CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES))->GetCurSel();
  5285.     m_iListStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
  5286.  
  5287.     // Set alignment if it was changed
  5288.     EDT_SetParagraphAlign( m_pMWContext, m_Align );
  5289.  
  5290.     // Default values
  5291.     TagType     iTagType = P_UNUM_LIST;
  5292.     ED_ListType iListItemType = ED_LIST_TYPE_DEFAULT;
  5293.     CComboBox * pListItemStyles = (CComboBox*)GetDlgItem(IDC_LIST_ITEM_STYLES);
  5294.  
  5295.     if( m_iContainerStyle == ED_BLOCKQUOTE ){
  5296.         iTagType = P_BLOCKQUOTE;
  5297.     } else if( m_iContainerStyle == ED_LIST ){
  5298.         switch( m_iListStyle ){
  5299.             case ED_NUM_LIST:
  5300.                 iTagType = P_NUM_LIST;
  5301.                 break;
  5302.             case ED_DIR_LIST:
  5303.                 iTagType = P_DIRECTORY;
  5304.                 break;
  5305.             case ED_MENU_LIST:
  5306.                 iTagType = P_MENU;
  5307.                 break;
  5308.             case ED_DESC_LIST:
  5309.                 iTagType = P_DESC_LIST;
  5310.                 break;
  5311.             //Note: UNUM_LIST is default
  5312.         }
  5313.  
  5314.         if( iTagType == P_UNUM_LIST ) {
  5315.             m_iBulletStyle = pListItemStyles->GetCurSel();
  5316.             switch( m_iBulletStyle ){
  5317.                 case ED_SOLID_CIRCLE:
  5318.                     iListItemType = ED_LIST_TYPE_DISC;
  5319.                     break;
  5320.                 case ED_OPEN_CIRCLE:
  5321.                     iListItemType = ED_LIST_TYPE_CIRCLE;
  5322.                     break;
  5323.                 case ED_SOLID_SQUARE:
  5324.                     iListItemType = ED_LIST_TYPE_SQUARE;
  5325.                     break;
  5326.             }
  5327.         } else if( iTagType == P_NUM_LIST ) {
  5328.             m_iNumberStyle = pListItemStyles->GetCurSel();
  5329.             switch( m_iNumberStyle ){
  5330.                 case ED_DIGIT:
  5331.                     iListItemType = ED_LIST_TYPE_DIGIT;
  5332.                     break;
  5333.                 case ED_BIG_ROMAN:
  5334.                     iListItemType = ED_LIST_TYPE_BIG_ROMAN;
  5335.                     break;
  5336.                 case ED_SMALL_ROMAN:
  5337.                     iListItemType = ED_LIST_TYPE_SMALL_ROMAN;
  5338.                     break;
  5339.                 case ED_BIG_LETTERS:
  5340.                     iListItemType = ED_LIST_TYPE_BIG_LETTERS;
  5341.                     break;
  5342.                 case ED_SMALL_LETTERS:
  5343.                     iListItemType = ED_LIST_TYPE_SMALL_LETTERS;
  5344.                     break;
  5345.             }
  5346.         }
  5347.     }
  5348.  
  5349.     //TODO: CHECK THIS -- WE MAY NOT WANT TO DO IT
  5350.     // We don't want a container but had one before
  5351.     if( m_pListData && m_iContainerStyle == ED_NO_CONTAINER ){
  5352.         // TODO: SHOULD WE UNDO INDENT FOR LIST ITEMS ALSO?
  5353. //        if ( iTagType == P_BLOCKQUOTE ) {
  5354.             EDT_ListData * pListData;
  5355.             // Repeat removing indent until last Unnumbered list is gone
  5356.             while ( (pListData = EDT_GetListData(m_pMWContext)) ){
  5357.                 EDT_FreeListData(pListData);
  5358.                 EDT_Outdent(m_pMWContext);
  5359.             }
  5360. //        }
  5361.     }
  5362.  
  5363.     // We should have been maintaining paragraph style
  5364.     //  to match container/list style, so this should work
  5365.     // But if "Don't change" style, NEVER set the container style
  5366.     if( m_iParagraphStyle != m_iMixedStyle ){
  5367.         TagType NewFormat = FEED_nParagraphTags[m_iParagraphStyle];
  5368.         if( m_ParagraphFormat != NewFormat ){
  5369.             EDT_MorphContainer( m_pMWContext, NewFormat);
  5370.         }
  5371.     }
  5372.  
  5373.     // We didn't already have a container but want one - create it
  5374.     if( ! m_pListData && m_iContainerStyle != ED_NO_CONTAINER) {
  5375.         EDT_Indent(m_pMWContext);
  5376.         m_pListData = EDT_GetListData(m_pMWContext);
  5377.     }
  5378.  
  5379.     // Set List type and attributes
  5380.     if ( m_pListData ) {
  5381.         // If no container, we Outdented above, so don't set data here
  5382.         if( m_iContainerStyle != ED_NO_CONTAINER ) {
  5383.             m_pListData->iTagType = iTagType;
  5384.             m_pListData->eType = iListItemType;
  5385.             m_pListData->bCompact = m_bCompact;
  5386.             m_pListData->iStart = m_iStartNumber;
  5387.         
  5388.             // Now we can change the list attribute:
  5389.             EDT_SetListData( m_pMWContext, m_pListData );
  5390.         }
  5391.     }
  5392.     OkToClose();
  5393.     //EDT_EndBatchChanges(m_pMWContext);
  5394. }
  5395.  
  5396. // Set listbox selected items depending on current state
  5397. // Primary key is m_iContainerStyle
  5398. // Other style values will be kept but ignored when setting
  5399. //   selected item or disabling/enabling dependent listboxes
  5400. // Goal is to show list style and bullet/numbering only if appropriate
  5401. //
  5402. void CParagraphPage::UpdateLists()
  5403. {
  5404.     // Set selected items    
  5405.     ((CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES))->SetCurSel(m_iParagraphStyle);
  5406.     ((CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES))->SetCurSel(m_iContainerStyle);
  5407.     
  5408.     // Remove and disable the selection in List Styles if not a List,
  5409.     //  else show what kind of list it is
  5410.     ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->SetCurSel( 
  5411.         m_iContainerStyle == ED_LIST ? m_iListStyle : -1);
  5412.     ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->EnableWindow(m_iContainerStyle == ED_LIST);
  5413.  
  5414.     // Rebuild the List Items styles list
  5415.     CComboBox * pListItemStyles = (CComboBox*)GetDlgItem(IDC_LIST_ITEM_STYLES);
  5416.     pListItemStyles->ResetContent();
  5417.  
  5418.     CWnd *pListItemLabel = GetDlgItem(IDC_LIST_ITEM_LABEL);
  5419.  
  5420.     BOOL bEnableStartNumber = FALSE;
  5421.     BOOL bEnableItemList = FALSE;
  5422.  
  5423.     if ( m_iContainerStyle == ED_LIST ){
  5424.         if( m_iListStyle == ED_UNUM_LIST ||
  5425.             m_iListStyle == ED_NUM_LIST ){
  5426.  
  5427.             pListItemStyles->EnableWindow(TRUE);
  5428.             pListItemStyles->AddString(szLoadString(IDS_AUTOMATIC));
  5429.             bEnableItemList = TRUE;
  5430.  
  5431.             if( m_iListStyle == ED_UNUM_LIST ){
  5432.                 // Be sure we are at least on the first item
  5433.                 m_iBulletStyle = max(0,m_iBulletStyle);
  5434.                 pListItemStyles->AddString(szLoadString(IDS_SOLID_CIRCLE));
  5435.                 pListItemStyles->AddString(szLoadString(IDS_OPEN_CIRCLE));
  5436.                 pListItemStyles->AddString(szLoadString(IDS_SOLID_SQUARE));
  5437.                 pListItemStyles->SetCurSel(m_iBulletStyle);
  5438.                 pListItemLabel->SetWindowText(szLoadString(IDS_BULLET_STYLE));
  5439.             } else if( m_iListStyle == ED_NUM_LIST ){
  5440.                 m_iNumberStyle = max(0,m_iNumberStyle);
  5441.                 pListItemStyles->AddString(szLoadString(IDS_DIGIT));
  5442.                 pListItemStyles->AddString(szLoadString(IDS_BIG_ROMAN));
  5443.                 pListItemStyles->AddString(szLoadString(IDS_SMALL_ROMAN));
  5444.                 pListItemStyles->AddString(szLoadString(IDS_BIG_LETTERS));
  5445.                 pListItemStyles->AddString(szLoadString(IDS_SMALL_LETTERS));
  5446.                 pListItemStyles->SetCurSel(m_iNumberStyle);
  5447.                 pListItemLabel->SetWindowText(szLoadString(IDS_NUMBER_STYLE));
  5448.                 bEnableStartNumber = TRUE;
  5449.             }
  5450.         }
  5451.     }
  5452.  
  5453.     // Set enable depending on bullet or number styles
  5454.     pListItemStyles->EnableWindow(bEnableItemList);
  5455.     if( !bEnableItemList ) {
  5456.         // Remove label if disabled
  5457.         pListItemLabel->SetWindowText("");
  5458.     } 
  5459.  
  5460.     // Disable start number if not a numbered list
  5461.     GetDlgItem(IDC_LIST_START_NUMBER)->EnableWindow(bEnableStartNumber);
  5462.  
  5463. }
  5464.  
  5465. void CParagraphPage::OnSelchangeParagraphStyles() 
  5466. {
  5467.     SetModified(TRUE);
  5468.     m_iParagraphStyle = ((CComboBox*)GetDlgItem(IDC_PARAGRAPH_STYLES))->GetCurSel();
  5469.  
  5470.     // Selecting a list item will force
  5471.     // List container and default type: Unnumbered List
  5472.     if( m_iParagraphStyle == ED_PARA_LIST ){
  5473.         m_iContainerStyle = ED_LIST;
  5474.         if( m_iListStyle == ED_DEFAULT ){
  5475.             m_iListStyle = ED_UNUM_LIST;
  5476.         }
  5477.     } else if( m_iParagraphStyle == ED_PARA_DESC_TITLE || m_iParagraphStyle == ED_PARA_DESC_TEXT){
  5478.         m_iContainerStyle = ED_LIST;
  5479.         if( m_iListStyle == ED_DEFAULT ){
  5480.             m_iListStyle = ED_DESC_LIST;
  5481.         }
  5482.     } else if( m_iContainerStyle == ED_LIST ){
  5483.         // Remove List container
  5484.         // Note that it is left as is for BLOCK QUOTE
  5485.         m_iContainerStyle = ED_NO_CONTAINER;
  5486.     }
  5487.     UpdateLists();
  5488. }
  5489.  
  5490. void CParagraphPage::OnSelchangeContainerStyle() 
  5491. {
  5492.     SetModified(TRUE);
  5493.     m_iContainerStyle = ((CComboBox*)GetDlgItem(IDC_CONTAINER_STYLES))->GetCurSel();
  5494.  
  5495.     // Force List paragraph style
  5496.     if( m_iContainerStyle == ED_LIST ){
  5497.         m_iParagraphStyle = ED_PARA_LIST;
  5498.  
  5499.         if( m_iListStyle == ED_DEFAULT ){
  5500.             m_iListStyle = ED_UNUM_LIST;
  5501.         }
  5502.     }
  5503.     UpdateLists();
  5504. }
  5505.  
  5506. void CParagraphPage::OnSelchangeListStyles() 
  5507. {
  5508.     SetModified(TRUE);
  5509.     m_iListStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
  5510.     // Reset Bullet/Numbering styles 
  5511.     //  depending on new List Style
  5512.     UpdateLists();
  5513. }
  5514.  
  5515. void CParagraphPage::OnSelchangeListItemStyle() 
  5516. {
  5517.     SetModified(TRUE);
  5518.     m_iListStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
  5519.     int iListItemStyle = ((CComboBox*)GetDlgItem(IDC_LIST_STYLES))->GetCurSel();
  5520.  
  5521.     // Just record index in proper list item category
  5522.     if( m_iListStyle == ED_UNUM_LIST){
  5523.         m_iBulletStyle = iListItemStyle;
  5524.     } else if( m_iListStyle == ED_NUM_LIST){
  5525.         m_iNumberStyle = iListItemStyle;
  5526.     }
  5527. }
  5528.  
  5529. void CParagraphPage::OnChangeListStartNumber() 
  5530. {
  5531.     SetModified(TRUE);
  5532. }
  5533.  
  5534. void CParagraphPage::OnAlignCenter() 
  5535. {
  5536.     m_Align = ED_ALIGN_ABSCENTER; // ED_ALIGN_CENTER;
  5537.     SetModified(TRUE);
  5538. }
  5539.  
  5540. void CParagraphPage::OnAlignLeft() 
  5541. {
  5542.     m_Align = ED_ALIGN_LEFT;
  5543.     SetModified(TRUE);
  5544. }
  5545.  
  5546. void CParagraphPage::OnAlignRight() 
  5547. {
  5548.     m_Align = ED_ALIGN_RIGHT;
  5549.     SetModified(TRUE);
  5550. }
  5551.  
  5552. void CParagraphPage::OnClose() 
  5553. {
  5554.     // We can't release data in OnOK 
  5555.     //  since we may stay around after
  5556.     //  it is called for "Apply" function
  5557.     if( m_pListData ){
  5558.         EDT_FreeListData(m_pListData);
  5559.     }
  5560.     CNetscapePropertyPage::OnClose();
  5561. }
  5562.  
  5563. //////////////////////////////////////////////////////////////////
  5564. IMPLEMENT_DYNAMIC(CColorButton, CButton)
  5565.  
  5566. CColorButton::CColorButton(COLORREF * pColorRef, COLORREF * pSetFocusColor) :
  5567.     m_pColorRef(pColorRef),
  5568.     m_pSetFocusColor(pSetFocusColor),
  5569.     m_hPal(0),
  5570.     m_bColorSwatchMode(0),
  5571.     m_pToolTip(0)
  5572. {
  5573. }
  5574.  
  5575. CColorButton::~CColorButton()
  5576. {
  5577.     if( m_pToolTip ){
  5578.         delete m_pToolTip;
  5579.     }
  5580. }
  5581.  
  5582. BEGIN_MESSAGE_MAP(CColorButton, CButton)
  5583.     //{{AFX_MSG_MAP(CColorButton)
  5584.     ON_WM_MOUSEMOVE()
  5585.     ON_WM_SETFOCUS()
  5586.     //}}AFX_MSG_MAP
  5587. #ifdef XP_WIN32
  5588.     ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify )
  5589. #endif
  5590. END_MESSAGE_MAP()
  5591.  
  5592. BOOL CColorButton::PreTranslateMessage(MSG* pMsg)
  5593. {
  5594.     if( m_pToolTip && pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
  5595.     {
  5596. #ifdef XP_WIN32 
  5597.                 // This is needed to get around an MFC bug
  5598.                 //   where tooltip is disabled after Modal Dialog is called
  5599.                 m_pToolTip->Activate(TRUE);
  5600. #endif
  5601.         m_pToolTip->RelayEvent(pMsg);
  5602.     }
  5603.     return CButton::PreTranslateMessage(pMsg);
  5604. }
  5605.  
  5606. // 
  5607. #ifdef XP_WIN32 
  5608. // This is needed for non-CFrame owners of a CToolTipCtrl
  5609. BOOL CColorButton::OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
  5610. {
  5611.     TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
  5612.     UINT nID =pNMHDR->idFrom;
  5613.     if (pTTT->uFlags & TTF_IDISHWND)
  5614.     {
  5615.         if(::GetDlgCtrlID((HWND)nID) == 1) {
  5616.             strcpy(pTTT->szText, m_pTipText);
  5617.             return(TRUE);
  5618.         }
  5619.     }
  5620.     return(FALSE);
  5621. }
  5622. #endif
  5623.  
  5624. BOOL CColorButton::Subclass(CWnd * pParentWnd, UINT nID, COLORREF * pColorRef, BOOL bColorSwatchMode)
  5625. {
  5626.     if(!pParentWnd || !pColorRef){
  5627.         return FALSE;
  5628.     }
  5629.     m_pColorRef = pColorRef;
  5630.     m_bColorSwatchMode = bColorSwatchMode;
  5631.  
  5632.     // Attach derived class to existing control and route messages to parent dialog
  5633.     BOOL bResult = SubclassDlgItem(nID, pParentWnd);
  5634.  
  5635.     // Must do subclass before we can use GetParentFrame()
  5636.     m_hPal = WFE_GetUIPalette(GetParentFrame());
  5637.  
  5638.     AddToolTip();        
  5639.  
  5640.     return bResult;
  5641. }
  5642.  
  5643. BOOL CColorButton::Create(RECT& rect, CWnd * pParentWnd, UINT nID, COLORREF * pColorRef, BOOL bColorSwatchMode)
  5644. {
  5645.     if(!pParentWnd || !pColorRef){
  5646.         return FALSE;
  5647.     }
  5648.     m_pColorRef = pColorRef;
  5649.     m_bColorSwatchMode = bColorSwatchMode;
  5650.  
  5651.     BOOL bResult = CButton::Create(NULL, BS_PUSHBUTTON|BS_OWNERDRAW|WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP,
  5652.                                    rect, pParentWnd, nID);  
  5653.     // Must do Create before we can use GetParentFrame()
  5654.     m_hPal = WFE_GetUIPalette(GetParentFrame());
  5655.     
  5656.     AddToolTip();        
  5657.  
  5658.     return bResult;
  5659. }
  5660.  
  5661. void CColorButton::Update()
  5662. {
  5663.     // Redraw the button
  5664.     Invalidate(FALSE);
  5665.     
  5666.     // Update tooltip for new color
  5667.     if( m_pToolTip ){
  5668.         // Make a tip with "R=xxx G=xxx B=xxx"
  5669.         wsprintf(m_pTipText, szLoadString(IDS_COLOR_TIP_FORMAT),
  5670.                  GetRValue(*m_pColorRef),GetGValue(*m_pColorRef),GetBValue(*m_pColorRef));
  5671.         strcat(m_pTipText, szLoadString(IDS_COLOR_TIP_HTML));
  5672.         char * pEnd = m_pTipText + strlen(m_pTipText);
  5673.         sprintf(pEnd, "#%02X%02X%02X",GetRValue(*m_pColorRef),GetGValue(*m_pColorRef),GetBValue(*m_pColorRef));
  5674.         m_pToolTip->UpdateTipText(m_pTipText, this, 1);
  5675.     }    
  5676. }
  5677.  
  5678. void CColorButton::AddToolTip()
  5679. {
  5680.     // Add tooltip only if a real button
  5681.     // In "color swatch mode", the parent CColorPicker
  5682.     //   has 1 tooltip associated with all the button controls
  5683.     if( !m_bColorSwatchMode ){
  5684.         // Add a tooltip control
  5685.         m_pToolTip = new CNSToolTip2;
  5686.  
  5687.         if(m_pToolTip && !m_pToolTip->Create(this, TTS_ALWAYSTIP) ){
  5688.             TRACE("Unable To create ToolTip\n");
  5689.             delete m_pToolTip;
  5690.             m_pToolTip = NULL;
  5691.             return;
  5692.         }
  5693.         // Lets use speedy tooltips
  5694.         m_pToolTip->SetDelayTime(200);
  5695. #ifdef XP_WIN32
  5696.         // We MUST do this for MFC tooltips
  5697.         EnableToolTips(TRUE);
  5698. #endif // WIN32
  5699.         RECT  rect;
  5700.         GetClientRect(&rect);
  5701.         m_pToolTip->AddTool(this, m_pTipText, &rect, 1);
  5702.         // Set the text to show the colors
  5703.         Update();
  5704.     } 
  5705. }
  5706.  
  5707. void CColorButton::OnMouseMove(UINT nFlags, CPoint point)
  5708. {
  5709.     CButton::OnMouseMove(nFlags, point);
  5710.     
  5711.     // For the "Color swatch" mode, automatically pull focus to
  5712.     //  the button with any mouse over
  5713.     if( m_bColorSwatchMode && GetFocus() != this ){
  5714.         // Set the color for the caller
  5715.         // This allows just mouse move to set the color
  5716.         //  after user presses Enter key without clicking on a color button
  5717.         //  and also lets us use OnOK() for all button clicks
  5718.         SetFocus();
  5719.     }
  5720. }
  5721.  
  5722. void CColorButton::OnSetFocus(CWnd* pOldWnd)
  5723. {
  5724.     // Send the color back to the caller
  5725.     if( m_pSetFocusColor ){
  5726.         *m_pSetFocusColor = *m_pColorRef;
  5727.     }
  5728.     CButton::OnSetFocus(pOldWnd);   
  5729. }
  5730.  
  5731. #define COLOR_DROPDOWN_WIDTH 10
  5732.  
  5733. void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  5734. {
  5735.     HPALETTE hOldPal = NULL;
  5736.     CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  5737.     if( m_hPal )
  5738.     {
  5739.         hOldPal = ::SelectPalette( pDC->m_hDC, m_hPal, FALSE );
  5740.     }
  5741.     BOOL bSelected = lpDIS->itemState & ODS_SELECTED;
  5742.  
  5743.     HDC  hDC = lpDIS->hDC;
  5744.     RECT rect = lpDIS->rcItem;
  5745.     if( !m_bColorSwatchMode )
  5746.     {
  5747.         // We can't draw on last pixels of right and bottom???
  5748.         rect.right--;
  5749.         rect.bottom--;
  5750.     }
  5751.  
  5752.     // Use the button face color as our background
  5753.     ::FillRect(hDC, &rect, sysInfo.m_hbrBtnFace);
  5754.  
  5755.     HPEN penShadow = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnShadow);
  5756.     HPEN penHighlight = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnHilite);
  5757.     HPEN penBlack = ::CreatePen(PS_SOLID, 1, RGB(0,0,0));
  5758.     HPEN penOld = (HPEN)::SelectObject(hDC, penBlack);
  5759.     
  5760.     RECT rectColor = rect;
  5761.  
  5762.     if( m_bColorSwatchMode )
  5763.     {
  5764.         // Draw the depressed 3D look like Window's color picker,
  5765.         // Note that there is a built-in blank border
  5766.         //   only focus rect draws on actual window borders
  5767.         ::InflateRect(&rect, -2, -2);
  5768.         rectColor.left += 4;
  5769.         rectColor.top += 4;
  5770.         rectColor.right -= 3;
  5771.         rectColor.bottom -= 3;
  5772.     } else {
  5773.         rectColor.left += 2;
  5774.         rectColor.top += 2;
  5775.         rectColor.bottom -= 1;
  5776.         rectColor.right -= (COLOR_DROPDOWN_WIDTH + 7); 
  5777.     }
  5778.     
  5779.     // Draw depressed border for color swatch
  5780.     ::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
  5781.     ::LineTo(hDC, rect.left+1, rect.top+1);
  5782.     ::LineTo(hDC, rect.right, rect.top+1);
  5783.  
  5784.     ::SelectObject(hDC, penShadow);
  5785.     ::MoveToEx(hDC, rect.left, rect.bottom, NULL);
  5786.     ::LineTo(hDC, rect.left, rect.top);
  5787.     ::LineTo(hDC, rect.right+1, rect.top);
  5788.  
  5789.     ::SelectObject(hDC, penHighlight);
  5790.     ::MoveToEx(hDC, rect.left+1, rect.bottom, NULL);
  5791.     ::LineTo(hDC, rect.right, rect.bottom);
  5792.     ::LineTo(hDC, rect.right, rect.top);
  5793.     
  5794.     ::SelectObject(hDC, penBlack);    
  5795.     
  5796.     if( !m_bColorSwatchMode ) 
  5797.     {
  5798.         ::InflateRect(&rect, -2, -2);
  5799.         rect.top++;
  5800.         rect.left = rect.right - (COLOR_DROPDOWN_WIDTH + 4); 
  5801.         
  5802.         // Location of drop-down arrow 
  5803.         // Width is actually COLOR_DROPDOWN_WIDTH-4, 
  5804.         // but LineTo needs extra pixel to end where we want
  5805.         int iTWidth = COLOR_DROPDOWN_WIDTH - 3; 
  5806.         int iTLeft = rect.right - iTWidth - 4;
  5807.         int iTTop = rect.top + ((rect.bottom - rect.top)/2) - 2;
  5808.  
  5809.         // Offset down and right for pressed-down state
  5810.         if( lpDIS->itemState & ODS_SELECTED )
  5811.         {
  5812.             iTLeft++;
  5813.             iTTop++;
  5814.         }
  5815.         // Draw the black drop-down triangle
  5816.         while( iTWidth >= 0 )
  5817.         {
  5818.             ::MoveToEx(hDC, iTLeft, iTTop, NULL);
  5819.             ::LineTo(hDC, iTLeft + iTWidth, iTTop);
  5820.             iTTop++;
  5821.             iTLeft++;
  5822.             iTWidth -= 2;
  5823.         }
  5824.  
  5825.         if( lpDIS->itemState & ODS_SELECTED )
  5826.         {
  5827.             rect.right++;
  5828.             rect.bottom++;
  5829.             HBRUSH brushShadow = ::CreateSolidBrush(sysInfo.m_clrBtnShadow|0x02000000);
  5830.             ::FrameRect(hDC, &rect, brushShadow);
  5831.             ::DeleteObject(brushShadow);
  5832.         } else {
  5833.             // Draw the raised 3D button shadows
  5834.             ::MoveToEx(hDC, rect.left, rect.bottom, NULL);
  5835.             ::LineTo(hDC, rect.right, rect.bottom);
  5836.             ::LineTo(hDC, rect.right, rect.top-1);
  5837.  
  5838.             ::SelectObject(hDC, penShadow);
  5839.             ::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
  5840.             ::LineTo(hDC, rect.right-1, rect.bottom-1);
  5841.             ::LineTo(hDC, rect.right-1, rect.top);
  5842.             ::SelectObject(hDC, penHighlight);
  5843.             ::MoveToEx(hDC, rect.left, rect.bottom-1, NULL);
  5844.             ::LineTo(hDC, rect.left, rect.top);
  5845.             ::LineTo(hDC, rect.right, rect.top);
  5846.         }
  5847.     }
  5848.     // Draw the color rectangle unless we have a "no color" or "default" state
  5849.     if( *m_pColorRef != NO_COLORREF && *m_pColorRef != DEFAULT_COLORREF)
  5850.     {
  5851.  
  5852.         HBRUSH brushColor = ::CreateSolidBrush((*m_pColorRef)|0x02000000); // Like PALETTERGB
  5853.         // Fill a rect with supplied color
  5854.         HBRUSH brushOld = (HBRUSH)::SelectObject(hDC, brushColor);
  5855.         ::FillRect(hDC, &rectColor, brushColor);
  5856.  
  5857.         ::SelectObject(hDC, brushOld);
  5858.         ::DeleteObject(brushColor);
  5859.     }
  5860.  
  5861.     // Manually draw the focus rect
  5862.     if( lpDIS->itemState & ODS_FOCUS )
  5863.     {
  5864.         RECT rectFocus;
  5865.         if( m_bColorSwatchMode  )
  5866.         {
  5867.             rectFocus = lpDIS->rcItem;
  5868.             rect.left++;
  5869.             rect.top++;
  5870.         } else {
  5871.             rectFocus = rectColor;
  5872.             ::InflateRect(&rectFocus, -1, -1);
  5873.         }
  5874.         ::DrawFocusRect(hDC, &rectFocus);
  5875.     }
  5876.  
  5877.     // Cleanup
  5878.     ::SelectObject(hDC, penOld);
  5879.     ::DeleteObject(penShadow);
  5880.     ::DeleteObject(penHighlight);
  5881.     ::DeleteObject(penBlack);
  5882.     
  5883.     if(m_hPal)
  5884.     {
  5885.         ::SelectPalette( pDC->m_hDC, hOldPal, FALSE );
  5886.     }
  5887. }
  5888.  
  5889. /////////////////////////////////////////////////////////////////////////////
  5890. // CBitmapPushButton
  5891. // Allows toolbar-like pushbutton behavior
  5892.  
  5893. CBitmapPushButton::CBitmapPushButton(BOOL bNoBorder) :
  5894.     m_bDown(0),
  5895.     m_bFocus(0),
  5896.     m_bSelected(0),
  5897.     m_hPal(0),
  5898.     m_bNoBorder(bNoBorder)
  5899. {
  5900. }
  5901.  
  5902. int CBitmapPushButton::OnCreate(LPCREATESTRUCT lpCreateStruct )
  5903. {
  5904.     if( -1 == CBitmapButton::OnCreate(lpCreateStruct) ){
  5905.         return -1;
  5906.     }
  5907.     // Get the global default palette
  5908.     m_hPal = WFE_GetUIPalette(GetParentFrame());
  5909.     return 0;
  5910. }
  5911.  
  5912. CBitmapPushButton::~CBitmapPushButton()
  5913. {
  5914. }
  5915.  
  5916.  
  5917. BEGIN_MESSAGE_MAP(CBitmapPushButton, CBitmapButton)
  5918.     //{{AFX_MSG_MAP(CBitmapPushButton)
  5919.     ON_WM_CREATE()
  5920.         // NOTE - the ClassWizard will add and remove mapping macros here.
  5921.     //}}AFX_MSG_MAP
  5922. END_MESSAGE_MAP()
  5923.  
  5924.  
  5925. BOOL CBitmapPushButton::LoadBitmap(UINT nBitmapID)
  5926. {
  5927.      // delete old bitmaps (if present)
  5928.     m_bitmap.DeleteObject();
  5929.     m_bitmapSel.DeleteObject();
  5930.     m_bitmapFocus.DeleteObject();
  5931.     m_bitmapDisabled.DeleteObject();
  5932.  
  5933.     if ( !m_bitmap.LoadBitmap( nBitmapID ) ) {
  5934.         return FALSE;
  5935.     }
  5936.     return TRUE;
  5937. }
  5938.  
  5939. void CBitmapPushButton::SetCheck(BOOL bCheck)
  5940. {
  5941.     BOOL bChanged = m_bDown != bCheck;
  5942.     m_bDown = bCheck;
  5943.     SetState(bCheck);    
  5944.     if(bChanged){
  5945.         // We need to force redraw sometimes
  5946.         Invalidate(FALSE);
  5947.     }
  5948. }
  5949.  
  5950. /////////////////////////////////////////////////////////////////////////////
  5951. // CBitmapPushButton message handlers
  5952. void CBitmapPushButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  5953. {
  5954.     // Save current focus state so we know what 
  5955.     //  button is pressed via keyboard in CDropdownToolbar handler
  5956.     m_bFocus = (lpDIS->itemState & ODS_FOCUS);
  5957.  
  5958.     // If our state is pushed down ("checked"),
  5959.     //  then always force selected bit so
  5960.     //  we don't unselect when losing focus
  5961.     if(m_bDown) {
  5962.         lpDIS->itemState |= ODS_SELECTED;
  5963.     }
  5964.  
  5965.     m_bSelected = lpDIS->itemState & ODS_SELECTED;
  5966.  
  5967.     // Draw the bitmap ourselves to do transparent overlay
  5968.  
  5969.     // Get the bitmap for the image
  5970.     HBITMAP hBmpImg = 0;
  5971.  
  5972.     if(m_bSelected && m_bitmapSel.m_hObject ){
  5973.         // HBITMAP(m_bitmapSel) doesn't work in old MFC (Win16)
  5974.         hBmpImg = (HBITMAP)m_bitmapSel.m_hObject;
  5975.     } else if( m_bFocus && m_bitmapFocus.m_hObject ) {
  5976.         hBmpImg = (HBITMAP)m_bitmapFocus.m_hObject;
  5977.     } else if ( (lpDIS->itemState & ODS_DISABLED) && m_bitmapDisabled.m_hObject ) {
  5978.         hBmpImg = (HBITMAP)m_bitmapDisabled.m_hObject;
  5979.     } else {
  5980.         // Check for no bitmap at all!
  5981.         if( !m_bitmap.m_hObject ){
  5982.             return;
  5983.         }
  5984.         hBmpImg = (HBITMAP)m_bitmap.m_hObject;
  5985.     }
  5986.  
  5987.     HDC  hDC = lpDIS->hDC;
  5988.     HDC  hBmpDC  = ::CreateCompatibleDC(hDC);
  5989.     RECT rect = lpDIS->rcItem;
  5990.  
  5991.     // Use the button face color as our background
  5992.     ::FillRect(hDC, &rect, sysInfo.m_hbrBtnFace);
  5993.  
  5994.     // If no bitmap, we must be disabled and no image supplied - leave blank TODO: GRAY IMAGE
  5995.     // WEIRD - m_bitmapDisabled.m_hObject is not NULL
  5996. //    if( hBmpImg ){
  5997.     if( ! (lpDIS->itemState & ODS_DISABLED) ){
  5998.  
  5999.         HBITMAP hOldBmp = (HBITMAP)::SelectObject(hBmpDC, hBmpImg);
  6000.  
  6001.         // Get this for the real bimap width and height
  6002.         BITMAP bmp;
  6003.         ::GetObject(hBmpImg, sizeof(bmp), &bmp);
  6004.         
  6005.         int x, y;
  6006.         // Center the image within the button    
  6007.         x = rect.left + ((rect.right - rect.left) - bmp.bmWidth) / 2;            
  6008.         y = rect.top + ((rect.bottom - rect.top) - bmp.bmHeight) / 2;
  6009.  
  6010.         // If button is pushed down, shift image right and down 1 pixel,
  6011.         //  (but only if not using supplied selected bitmap)
  6012.         if(m_bSelected && m_bitmapSel.m_hObject == NULL ){
  6013.             x++;
  6014.             y++;
  6015.         }    
  6016.  
  6017.         // Call the handy transparent blit function to paint the bitmap over whatever colors exist.
  6018.         ::FEU_TransBlt( hDC, x, y , bmp.bmWidth, bmp.bmHeight,
  6019.                         hBmpDC, 0, 0, m_hPal);
  6020.  
  6021.         ::SelectObject(hBmpDC, hOldBmp);
  6022.         ::DeleteDC(hBmpDC);
  6023.     }
  6024.  
  6025.     // Draw the 3D shadow borders
  6026.  
  6027.     // Reduce to use inclusive border
  6028.     rect.right --;
  6029.     rect.bottom --;
  6030.     ::InflateRect(&rect, -1, -1);
  6031.     HPEN penShadow = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnShadow);
  6032.     HPEN penHighlight = ::CreatePen(PS_SOLID, 1, sysInfo.m_clrBtnHilite);
  6033.     HPEN penBlack = ::CreatePen(PS_SOLID, 1, RGB(0,0,0));
  6034.     HPEN penOld = (HPEN)::SelectObject(hDC, penBlack);
  6035.  
  6036.     if( m_bSelected ){
  6037.         // Draw the depressed 3D button shadows
  6038.         //  only if bitmap wasn't supplied
  6039.         if( m_bitmapSel.m_hObject == NULL ){
  6040.             ::MoveToEx(hDC, rect.left, rect.bottom, NULL);
  6041.             ::LineTo(hDC, rect.left, rect.top);
  6042.             ::LineTo(hDC, rect.right+1, rect.top);
  6043.  
  6044.             ::SelectObject(hDC, penShadow);
  6045.             ::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
  6046.             ::LineTo(hDC, rect.left+1, rect.top+1);
  6047.             ::LineTo(hDC, rect.right, rect.top+1);
  6048.  
  6049.             ::SelectObject(hDC, penHighlight);
  6050.             ::LineTo(hDC, rect.right, rect.bottom);
  6051.             ::LineTo(hDC, rect.left, rect.bottom);
  6052.         }
  6053.     } else if( !m_bNoBorder ){
  6054.         // Draw the raised 3D button shadows
  6055.         ::MoveToEx(hDC, rect.left, rect.bottom, NULL);
  6056.         ::LineTo(hDC, rect.right, rect.bottom);
  6057.         ::LineTo(hDC, rect.right, rect.top-1);
  6058.  
  6059.         ::SelectObject(hDC, penShadow);
  6060.         ::MoveToEx(hDC, rect.left+1, rect.bottom-1, NULL);
  6061.         ::LineTo(hDC, rect.right-1, rect.bottom-1);
  6062.         ::LineTo(hDC, rect.right-1, rect.top);
  6063.  
  6064.         ::SelectObject(hDC, penHighlight);
  6065.         ::MoveToEx(hDC, rect.left, rect.bottom-1, NULL);
  6066.         ::LineTo(hDC, rect.left, rect.top);
  6067.         ::LineTo(hDC, rect.right, rect.top);
  6068.     }
  6069.  
  6070.     // Manually draw the focus rect if we don't have an image
  6071.     // This is optimized for a 1-pixel highlight bevel
  6072.     //   and 2-pixel shadow bevel
  6073.     // Note that CBitmapButton will NEVER
  6074.     //   show a distinct Selected+Focus state, 
  6075.     //   so this supplies that feature
  6076.     if( m_bFocus && m_bitmapFocus.m_hObject == NULL ){
  6077.         if( !m_bSelected ){
  6078.             // Draw the raised 3D button shadows if we are not pressing down
  6079.             ::SelectObject(hDC, penHighlight);
  6080.             ::MoveToEx(hDC, rect.left, rect.bottom-1, NULL);
  6081.             ::LineTo(hDC, rect.left, rect.top);
  6082.             ::LineTo(hDC, rect.right, rect.top);
  6083.  
  6084.             ::SelectObject(hDC, penShadow);
  6085.             ::MoveToEx(hDC, rect.left, rect.bottom, NULL);
  6086.             ::LineTo(hDC, rect.right, rect.bottom);
  6087.             ::LineTo(hDC, rect.right, rect.top-1);
  6088.         }
  6089.         // Draw a solid black frame just outside of 3D shadow rect
  6090.         ::InflateRect(&rect, 1, 1);
  6091.         // Stupid algorithm doesn't include actual right/bottom
  6092.         rect.bottom++;
  6093.         rect.right++;
  6094.         FrameRect(hDC, &rect, (HBRUSH)::GetStockObject(BLACK_BRUSH));
  6095.     }
  6096.  
  6097.     // Cleanup
  6098.     ::SelectObject(hDC, penOld);
  6099.     ::DeleteObject(penShadow);
  6100.     ::DeleteObject(penHighlight);
  6101.     ::DeleteObject(penBlack);
  6102. }
  6103.  
  6104. // Collection of Alignment/Size/Border controls used by 
  6105. //   Image, Java, and PlugIn dialogs
  6106. /////////////////////////////////////////////////////////////////////
  6107. CAlignControls::CAlignControls() :
  6108.     m_nIDAlign(0),
  6109.     m_EdAlign(ED_ALIGN_DEFAULT)
  6110. {
  6111. }
  6112.  
  6113. BOOL CAlignControls::Init(CWnd *pParent)
  6114. {
  6115.     ASSERT(pParent);
  6116.     m_pParent = pParent;
  6117.  
  6118.     // Load the bitmaps for our alignment buttons
  6119.     VERIFY(m_BtnAlignTop.AutoLoad(IDC_EDAL_T, pParent));
  6120.     VERIFY(m_BtnAlignCenter.AutoLoad(IDC_EDAL_C, pParent));
  6121.     VERIFY(m_BtnAlignCenterBaseline.AutoLoad(IDC_EDALCB, pParent));
  6122.     VERIFY(m_BtnAlignBottomBaseline.AutoLoad(IDC_EDAL_A, pParent));
  6123.     VERIFY(m_BtnAlignBottom.AutoLoad(IDC_EDAL_B, pParent));
  6124.     VERIFY(m_BtnAlignLeft.AutoLoad(IDC_EDAL_L, pParent));
  6125.     VERIFY(m_BtnAlignRight.AutoLoad(IDC_EDAL_R, pParent));
  6126.  
  6127.     // Intialize controls
  6128.     SetAlignment();
  6129.     return TRUE;
  6130. }
  6131.  
  6132. // Return if we really changed the align state
  6133. //  as compared to the previous state
  6134. BOOL CAlignControls::OnAlignButtonClick(UINT nID)
  6135. {
  6136.     if ( nID == 0 ) {
  6137.         nID = m_nIDAlign ? m_nIDAlign : IDC_EDAL_B;
  6138.     }
  6139.     BOOL bChanged = nID != m_nIDAlign;
  6140.     m_nIDAlign = nID;
  6141.  
  6142.     m_BtnAlignTop.SetCheck(m_nIDAlign == IDC_EDAL_T);
  6143.     m_BtnAlignCenter.SetCheck(m_nIDAlign == IDC_EDAL_C);
  6144.     m_BtnAlignCenterBaseline.SetCheck(m_nIDAlign == IDC_EDALCB);
  6145.     m_BtnAlignBottomBaseline.SetCheck(m_nIDAlign == IDC_EDAL_A);
  6146.     m_BtnAlignBottom.SetCheck(m_nIDAlign == IDC_EDAL_B);
  6147.     m_BtnAlignLeft.SetCheck(m_nIDAlign == IDC_EDAL_L);
  6148.     m_BtnAlignRight.SetCheck(m_nIDAlign == IDC_EDAL_R);
  6149.  
  6150.     if(bChanged &&
  6151.        m_pParent->IsKindOf(RUNTIME_CLASS(CPropertyPage))){
  6152.         ((CPropertyPage*)m_pParent)->SetModified(TRUE);
  6153.     }
  6154.     return bChanged;
  6155. }
  6156.  
  6157. ED_Alignment CAlignControls::GetAlignment()
  6158. {
  6159.     // NOTE: ED_ defines are backward for Center and Bottom
  6160.     //  we should change them in EDTTYPES.H, but too much
  6161.     //  other code depends on them being wrong!
  6162.     switch( m_nIDAlign ){
  6163.         case IDC_EDAL_T:
  6164.             m_EdAlign = ED_ALIGN_TOP;
  6165.             break;
  6166.         case IDC_EDAL_C:
  6167.             m_EdAlign = ED_ALIGN_CENTER;
  6168. //            m_EdAlign =  ED_ALIGN_ABSCENTER;
  6169.             break;
  6170.         case IDC_EDALCB:
  6171.             m_EdAlign =  ED_ALIGN_ABSCENTER;
  6172. //            m_EdAlign = ED_ALIGN_CENTER;
  6173.             break;
  6174.         case IDC_EDAL_B:
  6175.             m_EdAlign = ED_ALIGN_BOTTOM;
  6176. //            m_EdAlign = ED_ALIGN_ABSBOTTOM;
  6177.             break;
  6178.         case IDC_EDAL_L:
  6179.             m_EdAlign = ED_ALIGN_LEFT;
  6180.             break;
  6181.         case IDC_EDAL_R:
  6182.             m_EdAlign = ED_ALIGN_RIGHT;
  6183.             break;
  6184.         default:
  6185.             m_EdAlign = ED_ALIGN_BASELINE;
  6186.             break;
  6187.     }
  6188.     return m_EdAlign;
  6189. }
  6190.  
  6191. void CAlignControls::SetAlignment()
  6192. {
  6193.     OnAlignButtonClick(m_nIDAlign);
  6194. }
  6195.  
  6196.  
  6197. //////////////////////////////////////////////////
  6198. // Image dialog page.
  6199. // Note that we must supply Image data since we may be sharing
  6200. //   it with Href data. 
  6201. // Thus we need a flag to tell us to insert new image.
  6202. /////////////////////////////////////////////////////////////////////
  6203. CImagePage::CImagePage(CWnd* pParent, MWContext * pMWContext,
  6204.                        CEditorResourceSwitcher * pResourceSwitcher,
  6205.                        EDT_ImageData * pData, BOOL bInsert)
  6206.     : CNetscapePropertyPage(CImagePage::IDD),
  6207.       m_pMWContext(pMWContext),
  6208.       m_pResourceSwitcher(pResourceSwitcher),
  6209.       m_bActivated(0),
  6210.       m_bInsert(bInsert),
  6211.       m_pData(pData)
  6212. {
  6213.     ASSERT(pMWContext);
  6214.     ASSERT(pData);
  6215.  
  6216.     //{{AFX_DATA_INIT(CImagePage)
  6217.     m_csImage = _T("");
  6218.     m_csLowRes = _T("");
  6219.     m_csAltText = _T("");
  6220.     m_bNoSave = 0;
  6221.     m_bSetAsBackground = 0;
  6222.     m_iHeight = 0;
  6223.     m_iWidth = 0;
  6224.     m_iHSpace = 0;
  6225.     m_iVSpace = 0;
  6226.     m_iBorder = 0;
  6227.     m_bDefaultBorder = FALSE;
  6228.     m_iHeightPixOrPercent = 0;
  6229.     m_iWidthPixOrPercent = 0;
  6230.     m_bLockAspect = 1;
  6231.     //}}AFX_DATA_INIT
  6232.     m_csHref = _T("");
  6233.     m_csImageStart = _T(""); 
  6234.     m_csLastValidImage = _T("");
  6235. //    m_csLastValidLowRes = _T("");
  6236.     m_bValidImage = FALSE;
  6237. //    m_bValidLowRes = FALSE;
  6238.     m_bImageChanged = FALSE;
  6239.     m_bOriginalButtonPressed = FALSE;
  6240.     m_bLockAspect = TRUE;
  6241.     
  6242.     wfe_GetLayoutViewSize(pMWContext, &m_iFullWidth, &m_iFullHeight);
  6243.  
  6244. #ifdef XP_WIN32
  6245.     // Set the hInstance so we get template from editor's resource DLL
  6246.     m_psp.hInstance = AfxGetResourceHandle();
  6247. #endif
  6248. }
  6249.  
  6250. void CImagePage::DoDataExchange(CDataExchange* pDX)
  6251. {
  6252.     CPropertyPage::DoDataExchange(pDX);
  6253.     //{{AFX_DATA_MAP(CImagePage)
  6254.     DDX_Text(pDX, IDC_IMAGE_URL, m_csImage);
  6255.     DDX_Check(pDX, IDC_NO_SAVE_IMAGE, m_bNoSave);
  6256.     DDX_Check(pDX, IDC_LOCK_ASPECT, m_bLockAspect);
  6257.     DDX_Check(pDX, IDC_MAKE_IMAGE_BACKGROUND, m_bSetAsBackground);
  6258.     DDX_Text(pDX, IDC_IMAGE_HEIGHT, m_iHeight);
  6259.     DDV_MinMaxInt(pDX, m_iHeight, 0, 10000);
  6260.     DDX_Text(pDX, IDC_IMAGE_WIDTH, m_iWidth);
  6261.     DDV_MinMaxInt(pDX, m_iWidth, 0, 10000);
  6262.     DDX_Text(pDX, IDC_IMAGE_SPACE_HORIZ, m_iHSpace);
  6263.     DDV_MinMaxInt(pDX, m_iHSpace, 0, 1000);
  6264.     DDX_Text(pDX, IDC_IMAGE_SPACE_VERT, m_iVSpace);
  6265.     DDV_MinMaxInt(pDX, m_iVSpace, 0, 1000);
  6266.     DDX_Text(pDX, IDC_IMAGE_BORDER, m_iBorder);
  6267.     DDV_MinMaxInt(pDX, m_iBorder, 0, 1000);
  6268.     DDX_CBIndex(pDX, IDC_HEIGHT_PIX_OR_PERCENT, m_iHeightPixOrPercent);
  6269.     DDX_CBIndex(pDX, IDC_WIDTH_PIX_OR_PERCENT, m_iWidthPixOrPercent);
  6270.     //}}AFX_DATA_MAP
  6271. }
  6272.  
  6273.  
  6274. BEGIN_MESSAGE_MAP(CImagePage, CNetscapePropertyPage)
  6275.     //{{AFX_MSG_MAP(CImagePage)
  6276.     ON_BN_CLICKED(IDC_IMAGE_FILE, OnImageFile)
  6277.     ON_EN_CHANGE(IDC_IMAGE_URL, OnChangeImageURL)
  6278.     ON_EN_KILLFOCUS(IDC_LOWRES_URL, OnKillfocusImage)
  6279.     ON_BN_CLICKED(IDC_IMAGE_ORIGINAL_SIZE, OnImageOriginalSize)
  6280.     ON_BN_CLICKED(IDC_EDIT_IMAGE, OnEditImage)
  6281.     ON_BN_CLICKED(IDC_ALT_TEXT_LOWRES, OnAltTextLowRes)
  6282.     ON_BN_CLICKED(IDC_NO_SAVE_IMAGE, OnNoSave)
  6283.     ON_BN_CLICKED(IDC_REMOVE_ISMAP, OnRemoveIsmap)
  6284.     ON_BN_CLICKED(IDC_MAKE_IMAGE_BACKGROUND, OnSetAsBackground)
  6285.     ON_BN_CLICKED(IDC_EDAL_A, OnAlignBaseline)
  6286.     ON_BN_CLICKED(IDC_EDAL_B, OnAlignBottom)
  6287.     ON_BN_CLICKED(IDC_EDAL_C, OnAlignCenter)
  6288.     ON_BN_CLICKED(IDC_EDAL_L, OnAlignLeft)
  6289.     ON_BN_CLICKED(IDC_EDAL_R, OnAlignRight)
  6290.     ON_BN_CLICKED(IDC_EDAL_T, OnAlignTop)
  6291.     ON_BN_CLICKED(IDC_EDALCB, OnAlignCenterBaseline)
  6292.     ON_EN_CHANGE(IDC_IMAGE_HEIGHT, OnChangeHeight)
  6293.     ON_EN_CHANGE(IDC_IMAGE_WIDTH, OnChangeWidth)
  6294.     ON_CBN_SELCHANGE(IDC_HEIGHT_PIX_OR_PERCENT, OnSelchangeHeightPixOrPercent)
  6295.     ON_CBN_SELCHANGE(IDC_WIDTH_PIX_OR_PERCENT, OnSelchangeWidthPixOrPercent)
  6296.     ON_EN_CHANGE(IDC_IMAGE_SPACE_HORIZ, OnChangeSpaceHoriz)
  6297.     ON_EN_CHANGE(IDC_IMAGE_SPACE_VERT, OnChangeSpaceVert)
  6298.     ON_EN_CHANGE(IDC_IMAGE_BORDER, OnChangeBorder)
  6299.     ON_BN_CLICKED(IDC_EXTRA_HTML, OnExtraHTML)
  6300.     ON_BN_CLICKED(IDC_LOCK_ASPECT, OnLockAspect)
  6301.     //}}AFX_MSG_MAP
  6302. END_MESSAGE_MAP()
  6303.  
  6304. BOOL CImagePage::OnSetActive() 
  6305. {
  6306.     if(m_pResourceSwitcher && !m_bActivated){
  6307.         // We must be sure we have switched
  6308.         //  the first time here - before dialog creation
  6309.         m_pResourceSwitcher->switchResources();
  6310.     }
  6311.     if(!CPropertyPage::OnSetActive())
  6312.         return(FALSE);
  6313.  
  6314.     if(m_bActivated)
  6315.         return(TRUE);
  6316.     // Switch back to EXE's resources
  6317.     if( m_pResourceSwitcher ){
  6318.         m_pResourceSwitcher->Reset();
  6319.     }
  6320.  
  6321.     if ( m_pData->pSrc && XP_STRLEN(m_pData->pSrc) > 0 ){
  6322.         m_csImage = XP_STRDUP(m_pData->pSrc);
  6323.     }
  6324.     else if ( !m_bInsert ) {
  6325.         TRACE0("No Image Filename for Image Properties\n");
  6326.         return FALSE;
  6327.     }
  6328.  
  6329.     m_bActivated = TRUE;
  6330.  
  6331.     // Translate ImageData defines Align buttons index
  6332.     // NOTE: ED_ defines are backward for Center and Bottom
  6333.     //  we should change them in EDTTYPES.H, but too much
  6334.     //  other code depends on them being wrong!
  6335.     m_AlignControls.m_EdAlign = m_pData->align;
  6336.     switch ( m_pData->align ){
  6337.         case ED_ALIGN_LEFT:
  6338.             m_AlignControls.m_nIDAlign = IDC_EDAL_L;
  6339.             break;
  6340.         case ED_ALIGN_RIGHT:
  6341.             m_AlignControls.m_nIDAlign = IDC_EDAL_R;
  6342.             break;
  6343.         case ED_ALIGN_TOP:
  6344.         case ED_ALIGN_ABSTOP:
  6345.             m_AlignControls.m_nIDAlign = IDC_EDAL_T;
  6346.             break;
  6347.         case ED_ALIGN_ABSCENTER:
  6348.             m_AlignControls.m_nIDAlign = IDC_EDALCB;
  6349.             break;
  6350.         case ED_ALIGN_CENTER:
  6351.             m_AlignControls.m_nIDAlign = IDC_EDAL_C;
  6352.             break;
  6353.         case ED_ALIGN_BOTTOM:
  6354.             m_AlignControls.m_nIDAlign = IDC_EDAL_B;
  6355.             break;
  6356.         case ED_ALIGN_ABSBOTTOM:
  6357.         case ED_ALIGN_BASELINE:
  6358.         default:
  6359.             m_AlignControls.m_nIDAlign = IDC_EDAL_A;
  6360.             break;
  6361.     }
  6362.  
  6363.     // Intialize the common Alignment / Sizing controls;
  6364.     if ( !m_AlignControls.Init(this) ) {
  6365.         return FALSE;
  6366.     }
  6367.     // Use suplied values only if they existed,
  6368.     //  use our defaults (5 pixels) for new object
  6369.     if ( ! m_bInsert ){
  6370.         m_iVSpace = CASTINT(m_pData->iVSpace);
  6371.         m_iHSpace = CASTINT(m_pData->iHSpace);
  6372.     }
  6373.     if( m_pData->iBorder >= 0 ){
  6374.         m_iBorder = CASTINT(m_pData->iBorder);
  6375.     } else {
  6376.         // We were given the default border value of -1
  6377.         // Set flag to restore -1 if user doesn't change it,
  6378.         //  but it shows as 0 in the edit box
  6379.         m_bDefaultBorder = TRUE;
  6380.         m_iBorder = EDT_GetDefaultBorderWidth(m_pMWContext);
  6381.     }
  6382.     m_iWidth = CASTINT(m_pData->iWidth);
  6383.     m_iHeight = CASTINT(m_pData->iHeight);
  6384.     m_iHeightPixOrPercent = m_pData->bHeightPercent ? 1 : 0;
  6385.     m_iWidthPixOrPercent = m_pData->bWidthPercent ? 1 : 0;
  6386.  
  6387.     // We try to get the "Original" dimensions, or at least
  6388.     //  those when image was last loaded
  6389.     if( m_pData->iOriginalWidth ){
  6390.         m_iOriginalWidth = m_pData->iOriginalWidth;
  6391.         m_iOriginalHeight = m_pData->iOriginalHeight;
  6392.     } else {
  6393.         m_iOriginalWidth = m_pData->iWidth;
  6394.         m_iOriginalHeight = m_pData->iHeight;
  6395.     }
  6396.     // Avoid divide by zero
  6397.     m_iOriginalWidth = max(1, m_iOriginalWidth);
  6398.     m_iOriginalHeight = max(1, m_iOriginalHeight);
  6399.  
  6400.     // Fill drop-lists of units
  6401.     wfe_InitPixOrPercentCombos(this);
  6402.     
  6403.     // Controls specific to Image page:
  6404.     if ( m_pData->pLowSrc ){
  6405.         m_csLowRes = m_pData->pLowSrc;
  6406.     }
  6407.     m_csAltText = m_pData->pAlt;
  6408.  
  6409.     // Get possible HREF for image
  6410.     if(m_pData->pHREFData && m_pData->pHREFData->pURL){
  6411.         m_csHref = m_pData->pHREFData->pURL;
  6412.     }
  6413.     
  6414.     // Save initial image name to test
  6415.     //  before creating a link
  6416.     m_csImageStart = m_csImage;
  6417.     // Also save last valid image filenames
  6418.     m_csLastValidImage = m_csImage;
  6419. //    m_csLastValidLowRes = m_csLowRes;
  6420.     m_bImageChanged = FALSE;
  6421. //    m_bLowResChanged = FALSE;
  6422.  
  6423.     // Only allow removing bIsMap on images that already have it,
  6424.     //  i.e., we can't add it to raw images  (YET!)
  6425.     (GetDlgItem(IDC_REMOVE_ISMAP))->EnableWindow(m_pData->bIsMap);
  6426.  
  6427.  
  6428.  
  6429.     m_bNoSave = m_pData->bNoSave;
  6430.  
  6431.     SetLockAspectEnable();
  6432.     
  6433.     // Send data to controls
  6434.     UpdateData(FALSE);
  6435.     // Allow Apply button to be active if we are inserting a new object
  6436.     SetModified(m_bInsert);
  6437.     return(TRUE);
  6438. }
  6439.  
  6440. void CImagePage::OnHelp() 
  6441. {
  6442.     NetHelp(HELP_PROPS_IMAGE);
  6443. }
  6444.  
  6445. void CImagePage::OnOK() 
  6446. {
  6447.     //EDT_BeginBatchChanges(m_pMWContext);
  6448.  
  6449.  
  6450.     // Always set HREF data for image if struct exists, even if we didn't visit this page
  6451.     //  since the value may be changed by CLinkPage
  6452.     if( m_pData->pHREFData ){
  6453.         // If m_pData->pHREFData->pURL is NULL or empty, this clears any existing link
  6454.         EDT_SetHREFData(m_pMWContext, m_pData->pHREFData);
  6455.     }
  6456.  
  6457.     if(!m_bActivated ||
  6458.         // no change
  6459.         !IS_APPLY_ENABLED(this) ||
  6460.         // or error in data
  6461.         !UpdateData(TRUE) ) {
  6462.         //EDT_EndBatchChanges(m_pMWContext);
  6463.         return;
  6464.     }
  6465.  
  6466.  
  6467.     CleanupString(m_csImage);
  6468.  
  6469.     if ( m_csImage.IsEmpty() ){
  6470.         // No image -- do nothing 
  6471.         // WHAT IF THERE IS A LOWRES IMAGE??? ADD MESSAGEBOX?
  6472.         if ( m_bInsert ){
  6473.             return;
  6474.         }
  6475.         // TODO: delete current image here?
  6476.         // Currently, EDT_SetImageData does not check for m_pImageData = NULL;
  6477.         return;
  6478.     }
  6479.     // Validate/Relativize images
  6480.     // (Shouldn't really need this - validation is done on killfocus of edit boxes)
  6481.     if ( m_bImageChanged && !m_bValidImage ){
  6482.         if ( !wfe_ValidateImage( m_pMWContext, m_csImage ) ) {
  6483.             m_bValidImage = TRUE;
  6484.             UpdateData(FALSE);
  6485.             return;
  6486.         }
  6487.     }
  6488.     int iLastDot = m_csImage.ReverseFind('.');
  6489.     CString csExt;
  6490.     if(iLastDot > 0)
  6491.         csExt= m_csImage.Mid(iLastDot);
  6492.  
  6493.     //we must check to see if file is a bmp!
  6494.     if (0 == csExt.CompareNoCase(".bmp"))
  6495.     {
  6496.         char *t_outputfilename=wfe_ConvertImage(m_csImage.GetBuffer(0),(void *)this,m_pMWContext);
  6497.         if (t_outputfilename)
  6498.         {
  6499.             m_csImage=t_outputfilename;
  6500.             wfe_ValidateImage( m_pMWContext, m_csImage );
  6501.             XP_FREE(t_outputfilename);
  6502.             UpdateData(FALSE);//we need to update m_csImage!
  6503.         }
  6504.         else 
  6505.             return;
  6506.     }
  6507.     
  6508.     if( m_bSetAsBackground ){
  6509.         // Real simple - ignore all data except for image name and save
  6510.         EDT_PageData * pPageData = EDT_GetPageData(m_pMWContext);
  6511.         if( pPageData ){
  6512.             XP_FREEIF(pPageData->pBackgroundImage);
  6513.             pPageData->pBackgroundImage = XP_STRDUP((char*)LPCSTR(m_csImage));
  6514.             pPageData->bBackgroundNoSave = m_bNoSave;
  6515.             EDT_SetPageData(m_pMWContext, pPageData);
  6516.             EDT_FreePageData(pPageData);
  6517.         }
  6518.     } else {
  6519.         // Get the Alignment/Size data
  6520.         m_pData->align = m_AlignControls.GetAlignment();
  6521.         if( m_bOriginalButtonPressed ){
  6522.             // Trick backend into getting size from image,
  6523.             //   not the values edited
  6524.             m_pData->iWidth = 0;
  6525.             m_pData->iHeight = 0;
  6526.         } else {
  6527.             m_pData->iWidth = m_iWidth;
  6528.             m_pData->iHeight = m_iHeight;
  6529.         }
  6530.         m_pData->iHSpace = m_iHSpace;
  6531.         m_pData->iVSpace = m_iVSpace;
  6532.         if( m_bDefaultBorder ){
  6533.             m_pData->iBorder = -1;
  6534.         } else {
  6535.             m_pData->iBorder = m_iBorder;
  6536.         }
  6537.         m_pData->bWidthPercent = m_iWidthPixOrPercent;
  6538.         m_pData->bHeightPercent = m_iHeightPixOrPercent;
  6539.     
  6540.         // Data specific to Image:
  6541.         CleanupString(m_csLowRes);
  6542.         CleanupString(m_csAltText);
  6543.  
  6544.         if ( m_pData->pSrc ){
  6545.             XP_FREE(m_pData->pSrc);
  6546.         }
  6547.         m_pData->pSrc = XP_STRDUP(m_csImage);
  6548.  
  6549.         if ( m_pData->pLowSrc ){
  6550.             XP_FREE(m_pData->pLowSrc);
  6551.             m_pData->pLowSrc = NULL;
  6552.         }
  6553.  
  6554.         if ( !m_csLowRes.IsEmpty() ){
  6555.             m_pData->pLowSrc = XP_STRDUP(m_csLowRes);
  6556.         }
  6557.  
  6558.         // Note: deleting Alt text in editbox to remove Alt Text
  6559.         if ( m_pData->pAlt ){
  6560.             XP_FREE(m_pData->pAlt);
  6561.             m_pData->pAlt = NULL;
  6562.         }
  6563.         if ( !m_csAltText.IsEmpty() ){
  6564.             m_pData->pAlt = XP_STRDUP(m_csAltText);
  6565.         }
  6566.  
  6567.         m_pData->bNoSave = m_bNoSave;
  6568.         if ( m_bInsert )
  6569.             {
  6570.             EDT_InsertImage(m_pMWContext, m_pData, !m_bNoSave);
  6571.             // We insert just ONE image (on 1st "Apply" usage)
  6572.             // Thus other Apply or OK will modify newly-inserted image        
  6573.             m_bInsert = FALSE;
  6574.         }
  6575.         else {
  6576.             EDT_SetImageData(m_pMWContext, m_pData, !m_bNoSave);
  6577.         }
  6578.         //Note: ImageData and HrefData should be freed by caller
  6579.     }
  6580.  
  6581.     OkToClose();
  6582.     //EDT_EndBatchChanges(m_pMWContext);
  6583.     CPropertyPage::OnOK();
  6584. }
  6585.  
  6586. // Get and validate the Image name
  6587. // so it is up to date if we switch to the Link dialog page
  6588. BOOL CImagePage::OnKillActive()
  6589. {
  6590.     if( !UpdateData(TRUE) ){
  6591.         return FALSE;
  6592.     }
  6593.     if ( m_bImageChanged && !m_bValidImage ){
  6594.         wfe_ValidateImage( m_pMWContext, m_csImage );
  6595.     }
  6596.     if ( m_pData->pSrc ){
  6597.         XP_FREE(m_pData->pSrc);
  6598.     }
  6599.     m_pData->pSrc = XP_STRDUP(m_csImage);
  6600.  
  6601.     // Contrary to MFC help, this does NOT call our OnOK
  6602.     return CPropertyPage::OnKillActive();
  6603. }
  6604.  
  6605. // Called from the View after saving file to disk -- has new image
  6606. //   in a URL form relative to current document
  6607. void CImagePage::SetImageFileSaved(char * pImageURL, int iImageNumber )
  6608. {
  6609.     UpdateData(TRUE);
  6610.  
  6611.     if( iImageNumber == 1 ){
  6612.         m_csImage = pImageURL;
  6613.     } else if ( iImageNumber == 2 ) {
  6614.         m_csLowRes = pImageURL;
  6615.     }
  6616.     UpdateData(FALSE);
  6617. }
  6618.  
  6619. void CImagePage::OnImageFile()
  6620. {
  6621.     UpdateData(TRUE);
  6622.     char * szFilename = wfe_GetExistingImageFileName(this->m_hWnd, 
  6623.                                          szLoadString(IDS_SELECT_IMAGE), TRUE);
  6624.     if ( szFilename != NULL ){
  6625.         m_csImage = szFilename;
  6626.         // Note that we don't tell user if file is "bad" since
  6627.         //  it is difficult to validate in all cases
  6628.         wfe_ValidateImage( m_pMWContext, m_csImage );
  6629.         UpdateData(FALSE);
  6630.         XP_FREE( szFilename );
  6631.         SetModified(TRUE);
  6632.         UpdateData(FALSE);
  6633.         m_bValidImage = TRUE;
  6634.         m_csLastValidImage = m_csImage;
  6635.     }
  6636. }
  6637.  
  6638. void CImagePage::OnChangeImageURL()
  6639. {
  6640.     m_bImageChanged = TRUE;
  6641.     m_bValidImage = FALSE;
  6642.     SetModified(TRUE);
  6643.     // Disable Edit button if no image name
  6644.     GetDlgItem(IDC_IMAGE_URL)->GetWindowText(m_csImage);
  6645.     m_csImage.TrimLeft();
  6646.     m_csImage.TrimRight();
  6647.     GetDlgItem(IDC_EDIT_IMAGE)->EnableWindow(!m_csImage.IsEmpty());
  6648. }
  6649.  
  6650. void CImagePage::OnKillfocusImage() 
  6651. {
  6652.     if( m_bImageChanged &&
  6653.         UpdateData(TRUE) ){
  6654.         wfe_ValidateImage( m_pMWContext, m_csImage );
  6655.         m_bValidImage = TRUE;
  6656.         UpdateData(FALSE);
  6657.     }
  6658. }
  6659.  
  6660. void CImagePage::OnEditImage() 
  6661. {
  6662.    UpdateData(TRUE);
  6663.     // Get our view from the context and call edit method
  6664.    ((CNetscapeEditView*)WINCX(m_pMWContext)->GetView())->EditImage((char*)LPCSTR(m_csImage));
  6665. }
  6666.  
  6667. void CImagePage::SetLockAspectEnable()
  6668. {
  6669.     GetDlgItem(IDC_LOCK_ASPECT)->EnableWindow(!m_bSetAsBackground && !m_iHeightPixOrPercent && !m_iWidthPixOrPercent);
  6670. }
  6671.  
  6672. void CImagePage::OnSetAsBackground()
  6673. {
  6674.     m_bSetAsBackground = ((CButton*)GetDlgItem(IDC_MAKE_IMAGE_BACKGROUND))->GetCheck();
  6675.     // Enable or Disable all other controls - irrelevant when simply setting background
  6676.     GetDlgItem(IDC_EDAL_T)->EnableWindow(!m_bSetAsBackground);
  6677.     GetDlgItem(IDC_EDAL_C)->EnableWindow(!m_bSetAsBackground);
  6678.     GetDlgItem(IDC_EDALCB)->EnableWindow(!m_bSetAsBackground);
  6679.     GetDlgItem(IDC_EDAL_A)->EnableWindow(!m_bSetAsBackground);
  6680.     GetDlgItem(IDC_EDAL_B)->EnableWindow(!m_bSetAsBackground);
  6681.     GetDlgItem(IDC_EDAL_L)->EnableWindow(!m_bSetAsBackground);
  6682.     GetDlgItem(IDC_EDAL_R)->EnableWindow(!m_bSetAsBackground);
  6683.     GetDlgItem(IDC_IMAGE_HEIGHT)->EnableWindow(!m_bSetAsBackground);
  6684.     GetDlgItem(IDC_HEIGHT_PIX_OR_PERCENT)->EnableWindow(!m_bSetAsBackground);
  6685.     GetDlgItem(IDC_IMAGE_WIDTH)->EnableWindow(!m_bSetAsBackground);
  6686.     GetDlgItem(IDC_WIDTH_PIX_OR_PERCENT)->EnableWindow(!m_bSetAsBackground);
  6687.     GetDlgItem(IDC_IMAGE_ORIGINAL_SIZE)->EnableWindow(!m_bSetAsBackground);
  6688.     GetDlgItem(IDC_IMAGE_SPACE_HORIZ)->EnableWindow(!m_bSetAsBackground);
  6689.     GetDlgItem(IDC_IMAGE_SPACE_VERT)->EnableWindow(!m_bSetAsBackground);
  6690.     GetDlgItem(IDC_IMAGE_BORDER)->EnableWindow(!m_bSetAsBackground);
  6691.     GetDlgItem(IDC_ALT_TEXT_LOWRES)->EnableWindow(!m_bSetAsBackground);
  6692.     GetDlgItem(IDC_EXTRA_HTML)->EnableWindow(!m_bSetAsBackground);
  6693.     GetDlgItem(IDC_REMOVE_ISMAP)->EnableWindow(!m_bSetAsBackground && m_pData->bIsMap);
  6694.     SetLockAspectEnable();
  6695.     SetModified(TRUE);
  6696. }
  6697.  
  6698. void CImagePage::OnAltTextLowRes()
  6699. {
  6700.     CImageAltDlg dlg(this, m_pMWContext, m_csAltText, m_csLowRes);
  6701.     if( dlg.DoModal() ){
  6702.         // Get new strings only if they changed
  6703.         if( dlg.m_csAltText != m_csAltText ){
  6704.             SetModified(TRUE);
  6705.             m_csAltText  = dlg.m_csAltText;
  6706.         }
  6707.         if( dlg.m_csLowRes != m_csLowRes ){
  6708.             SetModified(TRUE);
  6709.             m_csLowRes = dlg.m_csLowRes;
  6710.         }
  6711.     }
  6712. }
  6713.  
  6714. void CImagePage::OnNoSave() 
  6715. {
  6716.     SetModified(TRUE);
  6717. }
  6718.  
  6719. void CImagePage::OnRemoveIsmap() 
  6720. {
  6721.     m_pData->bIsMap = FALSE;
  6722.     // Once removed, we can't add it back
  6723.     (GetDlgItem(IDC_REMOVE_ISMAP))->EnableWindow(FALSE);
  6724.     SetModified(TRUE);
  6725. }
  6726.  
  6727. // Align/Size controls:
  6728. void CImagePage::OnAlignBaseline() 
  6729. {
  6730.     m_AlignControls.OnAlignButtonClick(IDC_EDAL_A);
  6731. }
  6732.  
  6733. void CImagePage::OnAlignBottom() 
  6734. {
  6735.     m_AlignControls.OnAlignButtonClick(IDC_EDAL_B);
  6736. }
  6737.  
  6738. void CImagePage::OnAlignCenter() 
  6739. {
  6740.     m_AlignControls.OnAlignButtonClick(IDC_EDAL_C);
  6741. }
  6742.  
  6743. void CImagePage::OnAlignLeft() 
  6744. {
  6745.     m_AlignControls.OnAlignButtonClick(IDC_EDAL_L);
  6746. }
  6747.  
  6748. void CImagePage::OnAlignRight() 
  6749. {
  6750.     m_AlignControls.OnAlignButtonClick(IDC_EDAL_R);
  6751. }
  6752.  
  6753. void CImagePage::OnAlignTop() 
  6754. {
  6755.     m_AlignControls.OnAlignButtonClick(IDC_EDAL_T);
  6756. }
  6757.  
  6758. void CImagePage::OnAlignCenterBaseline() 
  6759. {
  6760.     m_AlignControls.OnAlignButtonClick(IDC_EDALCB);
  6761. }
  6762.  
  6763.  
  6764. void CImagePage::OnImageOriginalSize() 
  6765. {
  6766.     // Set flag so we're sure user wants this later
  6767.     m_bOriginalButtonPressed = TRUE;
  6768.     
  6769.     UpdateData(TRUE);
  6770.     
  6771.     m_iWidth = CASTINT(m_iOriginalWidth);
  6772.     m_iHeight = CASTINT(m_iOriginalHeight);
  6773.  
  6774.     // We must be in pixel mode, not % mode
  6775.     m_iHeightPixOrPercent = 0;
  6776.     m_iWidthPixOrPercent = 0;
  6777.  
  6778.     UpdateData(FALSE);
  6779.     SetModified(TRUE);
  6780. }
  6781.  
  6782. void CImagePage::OnChangeHeight() 
  6783. {
  6784.     if( m_bLockAspect && ((CButton*)GetDlgItem(IDC_LOCK_ASPECT))->IsWindowEnabled() ) {
  6785.         // Get value just enterred and set the opposite
  6786.         //  to a value that keeps aspect ratio of original
  6787.         CWnd *pHeightEdit = GetDlgItem(IDC_IMAGE_HEIGHT);
  6788.         CWnd *pWidthEdit = GetDlgItem(IDC_IMAGE_WIDTH);
  6789.         char  pValue[16];
  6790.         char* pEnd;
  6791.         pHeightEdit->GetWindowText(pValue, 10);
  6792.         int32 iHeight = (int)strtol( pValue, &pEnd, 10 );
  6793.     
  6794.         // Bad conversion if end pointer isn't at terminal null;
  6795.         if( *pEnd == '\0' ){
  6796.             m_iHeight = iHeight;
  6797.             // Add 0.5 to round off when converting back to int
  6798.             m_iWidth = (int)((iHeight * m_iOriginalWidth) / m_iOriginalHeight);
  6799.             wsprintf(pValue, "%d", m_iWidth);
  6800.             // Avoid bouncing back and forth (and killing stack!)
  6801.             // SetWindowText triggers OnChangeWidth
  6802.             m_bLockAspect = FALSE;
  6803.             pWidthEdit->SetWindowText(pValue);
  6804.             m_bLockAspect = TRUE;
  6805.         }
  6806.     }
  6807.     if( m_iHeight != m_iOriginalHeight){
  6808.         m_bOriginalButtonPressed = FALSE;
  6809.     }
  6810.     SetModified(TRUE);
  6811. }
  6812.  
  6813. void CImagePage::OnChangeWidth() 
  6814. {
  6815.     if( m_bLockAspect && ((CButton*)GetDlgItem(IDC_LOCK_ASPECT))->IsWindowEnabled() ){
  6816.         // Get value just enterred and set the opposite
  6817.         //  to a value that keeps aspect ratio of original
  6818.         CWnd *pWidthEdit = GetDlgItem(IDC_IMAGE_WIDTH);
  6819.         CWnd *pHeightEdit = GetDlgItem(IDC_IMAGE_HEIGHT);
  6820.         char  pValue[16];
  6821.         char* pEnd;
  6822.         pWidthEdit->GetWindowText(pValue, 10);
  6823.         int32 iWidth = (int32)strtol( pValue, &pEnd, 10 );
  6824.     
  6825.         if( *pEnd == '\0' ){
  6826.             m_iWidth = iWidth;
  6827.             m_iHeight = (int)((iWidth * m_iOriginalHeight) / m_iOriginalWidth);
  6828.             wsprintf(pValue, "%d", m_iHeight);
  6829.  
  6830.             // Avoid bouncing back and forth (and killing stack!)
  6831.             // SetWindowText triggers OnChangeHeight
  6832.             m_bLockAspect = FALSE;
  6833.             pHeightEdit->SetWindowText(pValue);
  6834.             m_bLockAspect = TRUE;
  6835.         }
  6836.     }
  6837.     if( m_iWidth != m_iOriginalWidth){
  6838.         m_bOriginalButtonPressed = FALSE;
  6839.     }
  6840.     SetModified(TRUE);
  6841. }
  6842.  
  6843. void CImagePage::OnSelchangeHeightPixOrPercent() 
  6844. {
  6845.     UpdateData();
  6846.     SetLockAspectEnable();
  6847.     //TODO: do number conversion if switching state?
  6848.     SetModified(TRUE);
  6849. }
  6850.  
  6851. void CImagePage::OnSelchangeWidthPixOrPercent() 
  6852. {
  6853.     UpdateData();
  6854.     SetLockAspectEnable();
  6855.     //TODO: do number conversion if switching state?
  6856.     SetModified(TRUE);
  6857. }
  6858.  
  6859. void CImagePage::OnChangeSpaceHoriz() 
  6860. {
  6861.     SetModified(TRUE);
  6862. }
  6863.  
  6864. void CImagePage::OnChangeSpaceVert() 
  6865. {
  6866.     SetModified(TRUE);
  6867. }
  6868.  
  6869.  
  6870. void CImagePage::OnChangeBorder() 
  6871. {
  6872.     SetModified(TRUE);
  6873.     // If user changed the border,
  6874.     //  then use that number instead
  6875.     //  of the default -1
  6876.     m_bDefaultBorder = FALSE;
  6877. }
  6878.  
  6879. void CImagePage::OnExtraHTML()
  6880. {
  6881.     CExtraHTMLDlg dlg(this, &m_pData->pExtra, IDS_IMG_TAG);
  6882.     if( dlg.DoModal() && dlg.m_bDataChanged ){
  6883.         SetModified(TRUE);
  6884.     }
  6885. }
  6886.  
  6887. void CImagePage::OnLockAspect()
  6888. {
  6889.     m_bLockAspect = ((CButton*)GetDlgItem(IDC_LOCK_ASPECT))->GetCheck();
  6890. }
  6891.  
  6892. /////////////////////////////////////////////////////////////////////////////
  6893. // CAltImageDlg dialog (modal popup over CImagePage for Alt text and Lowres Image)
  6894.  
  6895. CImageAltDlg::CImageAltDlg(CWnd *pParent,
  6896.                          MWContext *pMWContext,
  6897.                          CString& csAltText, 
  6898.                          CString& csLowRes )
  6899.     : CDialog(CImageAltDlg::IDD, pParent),
  6900.     m_pMWContext(pMWContext),
  6901.     m_bImageChanged(FALSE)
  6902. {
  6903.     //{{AFX_DATA_INIT(CImageAltDlg)
  6904.     m_csAltText = csAltText;
  6905.     m_csLowRes = csLowRes;
  6906.      //}}AFX_DATA_INIT
  6907.     ASSERT( pMWContext );
  6908. }
  6909.  
  6910. CImageAltDlg::~CImageAltDlg()
  6911. {
  6912. }
  6913.  
  6914. void CImageAltDlg::DoDataExchange(CDataExchange* pDX)
  6915. {
  6916.     CDialog::DoDataExchange(pDX);
  6917.     //{{AFX_DATA_MAP(CImageAltDlg)
  6918.     DDX_Text(pDX, IDC_LOWRES_URL, m_csLowRes);
  6919.     DDX_Text(pDX, IDC_IMAGE_ALT_TEXT, m_csAltText);
  6920.     //}}AFX_DATA_MAP
  6921. }
  6922.  
  6923.  
  6924. BEGIN_MESSAGE_MAP(CImageAltDlg, CDialog)
  6925.     //{{AFX_MSG_MAP(CImageAltDlg)
  6926.     ON_BN_CLICKED(IDC_IMAGE_FILE, OnLowResFile)
  6927.     ON_EN_CHANGE(IDC_LOWRES_URL, OnChangeLowResURL)
  6928.     ON_BN_CLICKED(IDC_EDIT_IMAGE, OnEditImage)
  6929.     ON_BN_CLICKED(ID_HELP, OnHelp)
  6930.     //}}AFX_MSG_MAP
  6931. #ifdef XP_WIN32
  6932.     ON_WM_HELPINFO()
  6933. #endif //XP_WIN32
  6934. END_MESSAGE_MAP()
  6935.  
  6936.  
  6937. BOOL CImageAltDlg::OnInitDialog() 
  6938. {
  6939.     // Switch back to NETSCAPE.EXE for resource hInstance
  6940.     m_ResourceSwitcher.Reset();
  6941.  
  6942.      CDialog::OnInitDialog();
  6943.  
  6944.     GetDlgItem(IDC_EDIT_IMAGE)->EnableWindow(!m_csLowRes.IsEmpty());
  6945.  
  6946.     return TRUE;  // return TRUE unless you set the focus to a control
  6947.                   // EXCEPTION: OCX Property Pages should return FALSE
  6948. }
  6949.  
  6950. void CImageAltDlg::OnHelp() 
  6951. {
  6952.     NetHelp(HELP_PROPS_IMAGE);    // TODO: ADD THIS TO HELP  
  6953. }
  6954.  
  6955. #ifdef XP_WIN32
  6956. BOOL CImageAltDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
  6957. {
  6958.     OnHelp();
  6959.     return TRUE;
  6960. }
  6961. #endif//XP_WIN32
  6962.  
  6963. void CImageAltDlg::OnOK() 
  6964. {
  6965.     CDialog::OnOK();    
  6966.     // Strip off leading and ending spaces
  6967.     m_csAltText.TrimLeft();
  6968.     m_csAltText.TrimRight();
  6969.     m_csLowRes.TrimLeft();
  6970.     m_csLowRes.TrimRight();
  6971.     if( !m_bImageChanged ){
  6972.         wfe_ValidateImage( m_pMWContext, m_csLowRes );
  6973.     }
  6974. }
  6975.  
  6976. void CImageAltDlg::OnLowResFile() 
  6977. {
  6978.     UpdateData(TRUE);
  6979.     char * szFilename = wfe_GetExistingImageFileName(this->m_hWnd, 
  6980.                                          szLoadString(IDS_SELECT_LOWRES_IMAGE), TRUE);
  6981.     if ( szFilename == NULL ){
  6982.         return;
  6983.     }
  6984.  
  6985.     m_csLowRes = szFilename;
  6986.     wfe_ValidateImage( m_pMWContext, m_csLowRes );
  6987.     m_bImageChanged = TRUE;
  6988.     UpdateData(FALSE);
  6989.     XP_FREE( szFilename );
  6990. }
  6991.  
  6992. void CImageAltDlg::OnChangeLowResURL()
  6993. {
  6994.     m_bImageChanged = FALSE;
  6995.     // Disable Edit button if no image name
  6996.     GetDlgItem(IDC_LOWRES_URL)->GetWindowText(m_csLowRes);
  6997.     m_csLowRes.TrimLeft();
  6998.     m_csLowRes.TrimRight();
  6999.     GetDlgItem(IDC_EDIT_IMAGE)->EnableWindow(!m_csLowRes.IsEmpty());
  7000. }
  7001.  
  7002. void CImageAltDlg::OnEditImage() 
  7003. {
  7004.    UpdateData(TRUE);
  7005.     // Get our view from the context and call edit method
  7006.    ((CNetscapeEditView*)WINCX(m_pMWContext)->GetView())->EditImage((char*)LPCSTR(m_csLowRes));
  7007. }
  7008.  
  7009. /////////////////////////////////////////////////////////////////////////////
  7010. // CExtraHTMLDlg dialog (modal popup over CImagePage or CLinkPage for Extra HTML
  7011.  
  7012. CExtraHTMLDlg::CExtraHTMLDlg(CWnd *pParent, char **ppExtraHTML, UINT nIDTagType)
  7013.     : CDialog(CExtraHTMLDlg::IDD, pParent),
  7014.     m_ppExtraHTML(ppExtraHTML),
  7015.     m_bDataChanged(FALSE),
  7016.     m_nIDTagType(nIDTagType)
  7017. {
  7018.     ASSERT( ppExtraHTML );
  7019.     //{{AFX_DATA_INIT(CExtraHTMLDlg)
  7020.     m_csExtraHTML = *ppExtraHTML;
  7021.      //}}AFX_DATA_INIT
  7022. }
  7023.  
  7024. CExtraHTMLDlg::~CExtraHTMLDlg()
  7025. {
  7026. }
  7027.  
  7028. void CExtraHTMLDlg::DoDataExchange(CDataExchange* pDX)
  7029. {
  7030.     CDialog::DoDataExchange(pDX);
  7031.     //{{AFX_DATA_MAP(CExtraHTMLDlg)
  7032.     DDX_Text(pDX, IDC_EXTRA_HTML_TEXT, m_csExtraHTML);
  7033.     //}}AFX_DATA_MAP
  7034. }
  7035.  
  7036.  
  7037. BEGIN_MESSAGE_MAP(CExtraHTMLDlg, CDialog)
  7038.     //{{AFX_MSG_MAP(CExtraHTMLDlg)
  7039.     ON_BN_CLICKED(ID_HELP, OnHelp)
  7040.     //}}AFX_MSG_MAP
  7041. #ifdef XP_WIN32
  7042.     ON_WM_HELPINFO()
  7043. #endif //XP_WIN32
  7044. END_MESSAGE_MAP()
  7045.  
  7046.  
  7047. BOOL CExtraHTMLDlg::OnInitDialog() 
  7048. {
  7049.     // Switch back to NETSCAPE.EXE for resource hInstance
  7050.     m_ResourceSwitcher.Reset();
  7051.  
  7052.      CDialog::OnInitDialog();
  7053.  
  7054.     // Insert the text describing the tag type into the message and display
  7055.     CString csMsg;
  7056.     AfxFormatString1( csMsg, IDS_EXTRA_HTML_MSG, szLoadString(m_nIDTagType) );
  7057.     GetDlgItem(IDC_EXTRA_HTML_MSG)->SetWindowText(LPCSTR(csMsg));
  7058.  
  7059.     return TRUE;  // return TRUE unless you set the focus to a control
  7060.                   // EXCEPTION: OCX Property Pages should return FALSE
  7061. }
  7062.  
  7063. void CExtraHTMLDlg::OnHelp() 
  7064. {
  7065.     NetHelp(HELP_EXTRA_HTML);
  7066. }
  7067.  
  7068. #ifdef XP_WIN32
  7069. BOOL CExtraHTMLDlg::OnHelpInfo(HELPINFO *)//32bit messagemapping.
  7070. {
  7071.     OnHelp();
  7072.     return TRUE;
  7073. }
  7074. #endif//XP_WIN32
  7075.  
  7076. void CExtraHTMLDlg::OnOK() 
  7077. {
  7078.     CDialog::OnOK();    
  7079.     // Strip off leading and ending spaces
  7080.     m_csExtraHTML.TrimLeft();
  7081.     m_csExtraHTML.TrimRight();
  7082.  
  7083.     // Did we already have some data?
  7084.     BOOL bHadExtra = 0 != *m_ppExtraHTML;
  7085.  
  7086.     if( !bHadExtra && m_csExtraHTML.IsEmpty() ){
  7087.         // We didn't have any before and none now, so we're done
  7088.         return;
  7089.     }
  7090.  
  7091.     if( bHadExtra && 0 == XP_STRCMP(*m_ppExtraHTML, LPCSTR(m_csExtraHTML)) ){
  7092.         // We had data before and it didn't change so we're done
  7093.         return;
  7094.     }
  7095.  
  7096.     // If here, new data must be different than previous text
  7097.     m_bDataChanged = TRUE;
  7098.     if( bHadExtra ) XP_FREE(*m_ppExtraHTML);
  7099.  
  7100.     if(m_csExtraHTML.IsEmpty() ){
  7101.         // No new text
  7102.         *m_ppExtraHTML = NULL;
  7103.     } else {
  7104.         // Copy new text
  7105.         *m_ppExtraHTML = XP_STRDUP(LPCSTR(m_csExtraHTML));
  7106.     }
  7107. }
  7108.  
  7109. ///////////////////////////////////////////////////////////////
  7110. // Links dialog page.
  7111. // Note that we must supply Href data since we may be sharing
  7112. //   it with Image data. If link is an image, *ppImage has name.
  7113. // Thus we need a flag to tell us to insert new link.
  7114. /////////////////////////////////////////////////////////////////////
  7115. CLinkPage::CLinkPage(CWnd* pParent, MWContext * pMWContext,
  7116.                      CEditorResourceSwitcher * pResourceSwitcher,
  7117.                      EDT_HREFData *pData, BOOL bInsert,
  7118.                      BOOL bMayHaveOtherLinks, char **ppImage)
  7119.     : CNetscapePropertyPage(CLinkPage::IDD),
  7120.       m_bActivated(0),
  7121.       m_bInsert(bInsert),
  7122.       m_pMWContext(pMWContext),
  7123.       m_pResourceSwitcher(pResourceSwitcher),
  7124.       m_bMayHaveOtherLinks(bMayHaveOtherLinks),
  7125.       m_ppImage(ppImage),
  7126.       m_pData(pData),
  7127.       m_iTargetCount(0),
  7128.       m_bValidHref(0),
  7129.       m_bHrefChanged(0),
  7130.       m_iCaretMovedBack(0)
  7131. {
  7132.     //}}AFX_DATA_INIT
  7133.     ASSERT(pMWContext);
  7134.     ASSERT(pData);
  7135.  
  7136.     m_szBaseDocument = NULL;
  7137.  
  7138.     // Base URL is the address of current document
  7139.     History_entry * hist_ent = SHIST_GetCurrent(&(m_pMWContext->hist));
  7140.     if ( hist_ent ){
  7141.         m_szBaseDocument = hist_ent->address;
  7142.     }
  7143.  
  7144.     // We will use some helper functions from our view
  7145.     m_pView = (CNetscapeView*)WINCX(pMWContext)->GetView();
  7146.  
  7147.     //{{AFX_DATA_INIT(CLinkPage)
  7148.     m_csHref = _T("");
  7149.     m_csAnchorEdit = _T("");
  7150.     m_csAnchor = _T("");
  7151.     //}}AFX_DATA_INIT
  7152.  
  7153.     m_csLastValidHref = _T("");
  7154.  
  7155. #ifdef XP_WIN32
  7156.     // Set the hInstance so we get template from editor's resource DLL
  7157.     m_psp.hInstance = AfxGetResourceHandle();
  7158. #endif
  7159. }
  7160.  
  7161. CLinkPage::~CLinkPage()
  7162. {
  7163.     // Reposition the caret to where it was
  7164.     //  when new link text was inserted
  7165.     while( m_iCaretMovedBack ){
  7166.         EDT_NextChar(m_pMWContext, FALSE);
  7167.         m_iCaretMovedBack--;
  7168.     }
  7169.  
  7170. }
  7171.  
  7172. void CLinkPage::DoDataExchange(CDataExchange* pDX)
  7173. {
  7174.     CPropertyPage::DoDataExchange(pDX);
  7175.     //{{AFX_DATA_MAP(CLinkPage)
  7176.         // NOTE: the ClassWizard will add DDX and DDV calls here
  7177.     DDX_Text(pDX, IDC_HREF_URL, m_csHref);
  7178.     DDX_Text(pDX, IDC_ANCHOR_EDIT, m_csAnchorEdit);
  7179.     DDX_Text(pDX, IDC_ANCHOR, m_csAnchor);
  7180.     //}}AFX_DATA_MAP
  7181. }
  7182.  
  7183. BEGIN_MESSAGE_MAP(CLinkPage, CNetscapePropertyPage)
  7184.     //{{AFX_MSG_MAP(CLinkPage)
  7185.     ON_BN_CLICKED(IDC_HREF_FILE, OnHrefFile)
  7186.     ON_BN_CLICKED(IDC_HREF_UNLINK, OnHrefUnlink)
  7187.     ON_LBN_SELCHANGE(IDC_TARGET_LIST, OnSelchangeTargetList)
  7188.     ON_EN_CHANGE(IDC_HREF_URL, OnChangeHrefUrl)
  7189.     ON_EN_KILLFOCUS(IDC_HREF_URL, OnKillfocusHrefUrl)
  7190.     ON_BN_CLICKED(IDC_TARGETS_IN_CURRENT_DOC, OnTargetsInCurrentDoc)
  7191.     ON_BN_CLICKED(IDC_TARGETS_IN_FILE, OnTargetsInFile)
  7192.     ON_BN_CLICKED(IDC_EXTRA_HTML, OnExtraHTML)
  7193.     //}}AFX_MSG_MAP
  7194. END_MESSAGE_MAP()
  7195.  
  7196. BOOL CLinkPage::OnSetActive() 
  7197. {
  7198.     if(m_pResourceSwitcher && !m_bActivated){
  7199.         // We must be sure we have switched
  7200.         //  the first time here - before dialog creation
  7201.         m_pResourceSwitcher->switchResources();
  7202.     }
  7203.     if(!CPropertyPage::OnSetActive())
  7204.         return(FALSE);
  7205.  
  7206.     BOOL bImageAnchor = FALSE;
  7207.  
  7208.     // Always check the Imagename that might
  7209.     //  be changed in the Image property page
  7210.     if( m_ppImage && *m_ppImage ){
  7211.         m_csAnchor = *m_ppImage;
  7212.         if(!m_csAnchor.IsEmpty()){
  7213.             ((CEdit*)GetDlgItem(IDC_ANCHOR))->SetWindowText(m_csAnchor);
  7214.             bImageAnchor = TRUE;
  7215.         }
  7216.     }
  7217.  
  7218.     if(m_bActivated)
  7219.         return(TRUE);
  7220.  
  7221.     // Switch back to EXE's resources
  7222.     if( m_pResourceSwitcher ){
  7223.         m_pResourceSwitcher->Reset();
  7224.     }
  7225.  
  7226.     m_bActivated = TRUE;
  7227.  
  7228.     // Get the current URL
  7229.     m_csHref = m_pData->pURL;
  7230.  
  7231.     //TODO: GET CURRENT CHARACTER STATE OR PASS IN?
  7232.  
  7233.  
  7234.     // Fill the "Display text" editbox
  7235.     //  with selected text     
  7236.     UINT nIDLabel = 0;
  7237.     BOOL bSelected = EDT_IsSelected(m_pMWContext);
  7238.  
  7239.     if (bImageAnchor){
  7240.         // Change label for image
  7241.         // (Note: We set Image filename string above)
  7242.         nIDLabel = IDS_ANCHOR_IMAGE;
  7243.     } else {
  7244.         if(m_bInsert && !bSelected ){
  7245.             // We will create/insert a new Anchor + Href at caret location
  7246.             // Use editbox instead of text control
  7247.             ((CEdit*)GetDlgItem(IDC_ANCHOR))->ShowWindow(SW_HIDE);
  7248.             nIDLabel = IDS_NEW_ANCHOR_TEXT;
  7249.         } 
  7250.         else if( EDT_CanSetHREF(m_pMWContext) ) {
  7251.             // We have a text link or selected text
  7252.             if ( bSelected ) {
  7253.                 m_csAnchor = (char*)LO_GetSelectionText(ABSTRACTCX(m_pMWContext)->GetDocumentContext());
  7254.             } else {
  7255.                 // We are not selected, but are within a text anchor
  7256.                 char * pText = EDT_GetHREFText(m_pMWContext);
  7257.                 m_csAnchor = pText;
  7258.                 XP_FREE(pText);
  7259.             }
  7260.             // Replace CR/LF with spaces to avoid ugly break in static display
  7261.             for( int i=0; i < m_csAnchor.GetLength(); i++ ){
  7262.                 if( m_csAnchor.GetAt(i) == '\r' || m_csAnchor.GetAt(i) == '\n' ){
  7263.                     m_csAnchor.SetAt(i, ' ');
  7264.                 }
  7265.             }
  7266.         }
  7267.     }
  7268.     if( nIDLabel ) {
  7269.         // Set label above image name or new text editbox
  7270.         GetDlgItem(IDC_ANCHOR_LABEL)->SetWindowText(szLoadString(nIDLabel));
  7271.     }
  7272.  
  7273.     if( nIDLabel != IDS_NEW_ANCHOR_TEXT ) {
  7274.         // Make the existing Anchor Text or Image Filename BOLD by using System Font
  7275. //        if( INTL_CharSetType(m_pMWContext->doc_csid) == SINGLEBYTE*/) {
  7276.             // This should be OK even in foreign systems
  7277.             CFont* pfontBold = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FONT));
  7278.             ((CEdit*)GetDlgItem(IDC_ANCHOR))->SetFont(pfontBold);
  7279. //        }
  7280.         // No editable anchor, so hide editbox
  7281.         (GetDlgItem(IDC_ANCHOR_EDIT))->ShowWindow(SW_HIDE);
  7282.     }
  7283.  
  7284.     // Save initial HREF to restore string
  7285.     //   if user changes to something invalid
  7286.     m_csLastValidHref = m_csHref;
  7287.  
  7288.     // Init unlink button state. Note that button shows
  7289.     //   if we may have other links within selection that we can remove
  7290.     (GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(!m_csHref.IsEmpty() || m_bMayHaveOtherLinks);
  7291.  
  7292.     // Get the list of Targets (named anchors) in current doc
  7293.     m_pTargetList = EDT_GetAllDocumentTargets(m_pMWContext);
  7294.     
  7295.     if( m_pTargetList == NULL ){
  7296.         // No targets in current doc, so disable button
  7297.         ((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->EnableWindow(FALSE);
  7298.     }
  7299.  
  7300.     // Try to generate a Targets list for current HREF (if local file),
  7301.     //  if none found, show the local list if it exists
  7302.     if ( 0 == GetTargetsInFile() && m_pTargetList ){
  7303.         if ( 0 == GetTargetsInDoc() ){
  7304.             (GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_NO_TARGETS));
  7305.         }
  7306.     }
  7307.     if( m_bMayHaveOtherLinks ){
  7308.         (GetDlgItem(IDC_HREF_UNLINK))->SetWindowText(szLoadString(IDS_REMOVE_LINKS));        
  7309.     }
  7310.  
  7311.     // Send data to controls
  7312.     UpdateData(FALSE);
  7313.     // Allow Apply button to be active if we are inserting a new object
  7314.     SetModified(m_bInsert);
  7315.     return(TRUE);
  7316. }
  7317.  
  7318. // Set the HREF data 
  7319. // It will be used by Image property page 
  7320. //   to set HREF to an image
  7321. BOOL CLinkPage::OnKillActive()
  7322. {
  7323.     if( !UpdateData() ){
  7324.         return FALSE;
  7325.     }
  7326.     if ( !m_bValidHref ){
  7327.         ValidateHref();
  7328.     }
  7329.     return CPropertyPage::OnKillActive();
  7330. }
  7331.  
  7332. int nTargetIndex = -1;
  7333.  
  7334. int CLinkPage::GetTargetsInDoc()
  7335. {
  7336.     m_iTargetCount = 0;
  7337.     CListBox * pListBox = (CListBox*)GetDlgItem(IDC_TARGET_LIST);
  7338.     pListBox->ResetContent();
  7339.  
  7340.     if( m_pTargetList ){
  7341.         char * pString = m_pTargetList;
  7342.         int iLen;    
  7343.         while( (iLen = XP_STRLEN(pString)) > 0 ) {
  7344.             // add to the end of the list
  7345.             pListBox->AddString(pString);
  7346.             pString += iLen+1;
  7347.             m_iTargetCount++;
  7348.         }
  7349.         ((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->SetCheck(1/*m_iTargetCount ? 1 : 0*/);
  7350.         ((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck(0);
  7351.  
  7352.         if( m_iTargetCount ){
  7353.             (GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_TARGETS_IN_CURRENT_DOC));
  7354.         }
  7355.     }
  7356.  
  7357.     return m_iTargetCount;
  7358. }
  7359.  
  7360. // File read from HTML to get list of anchors
  7361. int CLinkPage::GetTargetsInFile()
  7362. {
  7363.     if( m_csHref.IsEmpty() ){
  7364.         return 0;
  7365.     }
  7366.     m_iTargetCount = 0;
  7367.  
  7368.     // Build list from file
  7369.     char * pTargetList = EDT_GetAllDocumentTargetsInFile(
  7370.                                     m_pMWContext, (char*)LPCSTR(m_csHref));
  7371.     if( pTargetList ){
  7372.         CListBox * pListBox = (CListBox*)GetDlgItem(IDC_TARGET_LIST);
  7373.         pListBox->ResetContent();
  7374.         char * pString = pTargetList;
  7375.         int iLen;    
  7376.         while( (iLen = XP_STRLEN(pString)) > 0 ) {
  7377.             // add to the end of the list
  7378.             pListBox->AddString(pString);
  7379.             pString += iLen+1;
  7380.             m_iTargetCount++;
  7381.         }
  7382.  
  7383.         XP_FREE(pTargetList);
  7384.         // Save filename so we can avoid rereading file needlessly
  7385.         m_csTargetFile = m_csHref;
  7386.     } else {
  7387.         // HREF wasn't a file or
  7388.         //  was same as current
  7389.         // TODO: How can we know if current URL is same as HREF?
  7390.         ((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck(0);
  7391.         return 0;
  7392.     }
  7393.  
  7394.     ((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->SetCheck(0);
  7395.     ((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck( m_iTargetCount ? 1 : 0);
  7396.         
  7397.     // Set appropriate message above targets list
  7398.     if ( m_iTargetCount ){
  7399.         (GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_TARGETS_IN_FILE));
  7400.     } else {
  7401.         (GetDlgItem(IDC_TARGET_LABEL))->SetWindowText(szLoadString(IDS_NO_TARGETS));
  7402.     }
  7403.     return m_iTargetCount;
  7404. }
  7405.  
  7406.  
  7407. void CLinkPage::OnTargetsInCurrentDoc() 
  7408. {
  7409.     if( m_pTargetList ){
  7410.         GetTargetsInDoc();
  7411.     }
  7412. }
  7413.  
  7414. void CLinkPage::OnTargetsInFile() 
  7415. {
  7416.     UpdateData();
  7417.     GetTargetsInFile();
  7418. }
  7419.  
  7420. void CLinkPage::OnSelchangeTargetList() 
  7421. {
  7422.     UpdateData(TRUE);
  7423.     SetModified(TRUE);
  7424.     m_bValidHref = FALSE;
  7425.  
  7426.     // Copy selection text
  7427.     int nSel = ((CListBox*)GetDlgItem(IDC_TARGET_LIST))->GetCurSel();
  7428.  
  7429.     nTargetIndex = nSel;
  7430.     if( ((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->GetCheck() ){
  7431.         // For current doc, we need just the target
  7432.         m_csHref = '#';
  7433.     } else {
  7434.         // For file, append target to current HREF,
  7435.         // but strip off existing target first
  7436.         int iHash = m_csHref.Find('#');
  7437.         if( iHash>=0 ){
  7438.             m_csHref = m_csHref.Left(iHash+1);
  7439.         } else {
  7440.             m_csHref += '#';
  7441.         }
  7442.     }
  7443.     CString csTarget;
  7444.     ((CListBox*)GetDlgItem(IDC_TARGET_LIST))->GetText(nSel, csTarget);
  7445.     m_csHref += csTarget;
  7446.     (GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(TRUE);
  7447.     UpdateData(FALSE);
  7448. }
  7449.  
  7450. void CLinkPage::OnHrefFile() 
  7451. {
  7452.     // Get data from dialog
  7453.     if ( !UpdateData(TRUE) ){
  7454.         return;
  7455.     }
  7456.     // Note that the file filter is set to *.html,
  7457.     //   but all other file types are also available
  7458.     CString csFile = wfe_GetExistingFileName(this->m_hWnd,
  7459.                        szLoadString(IDS_LINK_TO_FILE), HTM, TRUE);
  7460.     if( !csFile.IsEmpty() ) {
  7461.         WFE_ConvertFile2Url(m_csHref, csFile);
  7462.         // Convert to a relative URL and validate
  7463.         ValidateHref();
  7464.         UpdateData(FALSE);
  7465.         SetModified(TRUE);
  7466.         // Try to get list of targets from local file
  7467.         OnTargetsInFile();
  7468.     }
  7469. }
  7470.  
  7471. void CLinkPage::OnHrefUnlink() 
  7472. {
  7473.     SetModified(TRUE);
  7474.  
  7475.     // Clear link from our member variable and 
  7476.     //   the passed-in data, and the edit box
  7477.     m_csHref = "";
  7478.     if(m_pData->pURL){
  7479.         XP_FREE(m_pData->pURL);
  7480.         m_pData->pURL = NULL;
  7481.     }
  7482.     ((CEdit *)GetDlgItem(IDC_HREF_URL))->SetWindowText("");
  7483.  
  7484.     ED_ElementType type = EDT_GetCurrentElementType(m_pMWContext);
  7485.     if( (m_bMayHaveOtherLinks && type == ED_ELEMENT_SELECTION /*|| 
  7486.          (type == ED_ELEMENT_SELECTION && EDT_CanSetHREF(m_pMWContext)) */) &&
  7487.              IDYES == MessageBox(szLoadString(IDS_REMOVE_OTHER_LINKS),
  7488.                                szLoadString(IDS_REMOVE_LINKS_CAPTION),
  7489.                                MB_ICONQUESTION | MB_YESNO) ){
  7490.         // Remove just the HREF immediately using masked bits        
  7491.         EDT_CharacterData *pCharData = EDT_NewCharacterData();
  7492.         if( pCharData ){
  7493.             pCharData->mask = TF_HREF;
  7494.             // "New" should set all values = 0;
  7495.             EDT_SetCharacterData(m_pMWContext, pCharData);
  7496.             EDT_FreeCharacterData(pCharData);
  7497.             // We now have no links to remove
  7498.             m_bMayHaveOtherLinks = FALSE;
  7499.             // and our action is similar to Apply button
  7500.             //  in that we commited an action
  7501.             OkToClose();
  7502.             (GetDlgItem(IDC_HREF_UNLINK))->SetWindowText(szLoadString(IDS_REMOVE_LINK));
  7503.         }
  7504.     }
  7505.     (GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(FALSE);
  7506. }
  7507.  
  7508. void CLinkPage::OnChangeHrefUrl() 
  7509. {
  7510.     SetModified(TRUE);
  7511.     m_bHrefChanged = TRUE;
  7512.     m_bValidHref = FALSE;
  7513.     // We only need HREF, so don't bother with UpdateData()
  7514.     CString csHREF;
  7515.     GetDlgItem(IDC_HREF_URL)->GetWindowText(csHREF);
  7516.     CleanupString(csHREF);
  7517.  
  7518.     if( csHREF.IsEmpty() ){
  7519.         // No URL, seems safe to redisplay the current list
  7520.         GetTargetsInDoc();
  7521.     } else if( (m_iTargetCount &&
  7522.                 ((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->GetCheck()) ||
  7523.                (((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->GetCheck() &&
  7524.                 m_csHref.Find(LPCSTR(m_csTargetFile)) == -1) ){
  7525.         // We had a current target list, or URL was changed
  7526.         //   so it isn't the same as the last target file used.
  7527.         // To remove uncertainty of what the target list refers to, remove it
  7528.         m_iTargetCount = 0;
  7529.         m_csTargetFile.Empty();
  7530.         ((CListBox*)GetDlgItem(IDC_TARGET_LIST))->ResetContent();
  7531.         ((CButton*)GetDlgItem(IDC_TARGETS_IN_CURRENT_DOC))->SetCheck(0);
  7532.         ((CButton*)GetDlgItem(IDC_TARGETS_IN_FILE))->SetCheck(0);
  7533.     }
  7534.     (GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(!csHREF.IsEmpty() || m_bMayHaveOtherLinks);
  7535.  
  7536.     // Update the common data structure with new HREF
  7537.     // Can't use SetHrefData() cause we can't change m_csHREF
  7538.     if(m_pData->pURL){
  7539.         XP_FREE(m_pData->pURL);
  7540.         m_pData->pURL = NULL;
  7541.     }
  7542.     if(!csHREF.IsEmpty()){
  7543.         m_pData->pURL = XP_STRDUP(csHREF);
  7544.     }
  7545. }
  7546.  
  7547. // Validate only after user leaves edit box
  7548. void CLinkPage::OnKillfocusHrefUrl() 
  7549. {
  7550.     if(m_bHrefChanged && UpdateData(TRUE)){
  7551.         ValidateHref();
  7552.     }
  7553. }
  7554.  
  7555. // Check for valid Href - convert to relative URL
  7556. // NOTE: Data must be read from control via DDX first
  7557. // This logic assumes that base document is local file,
  7558. // (We force saving a remote document before changing links)
  7559. void CLinkPage::ValidateHref()
  7560. {
  7561.     m_bValidHref = TRUE;
  7562.     CleanupString(m_csHref);
  7563.  
  7564.     // Empty is OK - this is how we remove links
  7565.     if ( m_csHref.IsEmpty() ){
  7566.         m_csLastValidHref.Empty();
  7567.         return;
  7568.     }
  7569.     // Strip off "#named_anchor" part and place in 
  7570.     //  separate string???
  7571.  
  7572.     XP_Bool bKeepLinks;
  7573.     PREF_GetBoolPref("editor.publish_keep_links",&bKeepLinks);
  7574.     if ( FE_ResolveLinkURL(m_pMWContext, m_csHref,bKeepLinks) ) {
  7575.         // Save this as a valid reference
  7576.         m_csLastValidHref = m_csHref;
  7577.     } else {
  7578.         // Error or user rejected the Href,
  7579.         //   restore to previous value
  7580.         m_csHref = m_csLastValidHref;
  7581.         SetModified(TRUE);
  7582.         UpdateData(FALSE);
  7583.     }
  7584.     // We must always set the HREF data immediately 
  7585.     //  common data because it will be accessed by
  7586.     //  CImagePage::OnOK before CLinkPage::OnOK
  7587.     SetHrefData();
  7588. }
  7589.  
  7590. void CLinkPage::SetHrefData()
  7591. {
  7592.     if(m_pData->pURL){
  7593.         XP_FREE(m_pData->pURL);
  7594.         m_pData->pURL = NULL;
  7595.     }
  7596.     if(!m_csHref.IsEmpty()){
  7597.         m_pData->pURL = XP_STRDUP(m_csHref);
  7598.     }
  7599.     //TODO: Set pTarget and pMocha strings
  7600. #if 0
  7601.     // Use this if we supply UI to change target frame
  7602.     // For now, just pass through what's there?
  7603.     if(m_pData->pTarget){
  7604.         XP_FREE(m_pData->pTarget);
  7605.         m_pData->pTarget = NULL;
  7606.     }
  7607.     if(!m_csTarget.IsEmpty()){
  7608.         m_pData->pTarget = XP_STRDUP(m_csTarget);
  7609.     }
  7610. #endif
  7611. }
  7612.  
  7613. void CLinkPage::OnExtraHTML()
  7614. {
  7615.     CExtraHTMLDlg dlg(this, &m_pData->pExtra, IDS_HREF_TAG);
  7616.     if( dlg.DoModal() && dlg.m_bDataChanged ){
  7617.         SetModified(TRUE);
  7618.     }
  7619. }
  7620.  
  7621. void CLinkPage::OnHelp() 
  7622. {
  7623.     NetHelp(HELP_PROPS_LINK);
  7624. }
  7625.  
  7626. void CLinkPage::OnOK() 
  7627. {
  7628.     CPropertyPage::OnOK();
  7629.  
  7630.     // never visited this page or no change -- don't bother
  7631.     if(!m_bActivated ||
  7632.        !IS_APPLY_ENABLED(this)){
  7633.         return;
  7634.     }    
  7635.  
  7636.     GetDlgItem(IDC_HREF_URL)->GetWindowText(m_csHref);
  7637.     CleanupString(m_csHref);
  7638.  
  7639.     //EDT_BeginBatchChanges(m_pMWContext);
  7640.  
  7641.     CleanupString(m_csAnchorEdit);
  7642.     int nResult = 0;
  7643.     // TODO: Test nResult for valid URL and add messages to user
  7644.     //   when there are problems
  7645.  
  7646.     if ( m_iTargetCount ) {
  7647.         nTargetIndex = ((CListBox*)GetDlgItem(IDC_TARGET_LIST))->GetCurSel();
  7648.         //TODO: Append the "#named_anchor" to the m_csHref;
  7649.     }
  7650.  
  7651.     // If we have an image Anchor, the image property page
  7652.     //  will set HREF data. 
  7653.     if( ! (m_ppImage && *m_ppImage && **m_ppImage != '\0') ){
  7654.         if ( EDT_CanSetHREF(m_pMWContext) ) {
  7655.             // Associate a URL with selected text 
  7656.             //   or existing link (text or image anchor)
  7657.             // TODO: LLOYD: return error: nResult = 
  7658.             // EDT_SetHREF( m_pMWContext, szURL );
  7659.             EDT_SetHREFData(m_pMWContext, m_pData);
  7660.             // Note: This will remove a link if m_pData->pURL is NULL
  7661.         }
  7662.         else /* if(m_pData->pURL) */{
  7663.             // We created a new link - 
  7664.             // Anchor text should have beeen typed
  7665.             char * szAnchor;
  7666.             if ( m_csAnchorEdit.IsEmpty() ) {
  7667.                 // No anchor text supplied, use URL
  7668.                 szAnchor = m_pData->pURL;
  7669.             } else {
  7670.                 // Can't do cast of LPCSTR() directly! Gives syntax error!
  7671.                 const char * szStupidCompiler = LPCSTR(m_csAnchorEdit);
  7672.                 szAnchor = (char*)szStupidCompiler; // (char*)(LPCSTR(m_csAnchorEdit));
  7673.             }
  7674.             if( m_bInsert && m_pData->pURL ) {
  7675.                 // Insert both Anchor text and Href
  7676.                 // TODO: LLOYD: return error: nResult = 
  7677.                 EDT_PasteHREF( m_pMWContext, &m_pData->pURL, &szAnchor, 1 );
  7678.                 // Set flag so future Apply actions will not insert another link
  7679.                 m_bInsert = FALSE;
  7680.                 // Move back one character so subsequent attributes Applied
  7681.                 //  don't include following text.
  7682.                 EDT_PreviousChar( m_pMWContext, FALSE );
  7683.                 m_iCaretMovedBack++;
  7684.                 
  7685.                 // Get the text just inserted
  7686.                 char * pNewText = EDT_GetHREFText(m_pMWContext);
  7687.                 if( pNewText == NULL ){
  7688.                     // If we insert a space after text, then
  7689.                     //  the link text will be empty.
  7690.                     //  We need to move back another character
  7691.                     //  so current text element is the text, not the space,
  7692.                     //  else subsequent calls to EDT_SetHREFData will
  7693.                     //  attach URL to space and following text, not the 
  7694.                     //  newly-inserted text
  7695.                     EDT_PreviousChar( m_pMWContext, FALSE );
  7696.                     m_iCaretMovedBack++;
  7697.                 } else {
  7698.                     XP_FREE(pNewText);
  7699.                 }
  7700.                     
  7701.                 // and set flag so we move forward upon exiting
  7702.  
  7703.                 // It would be a pain to allow replacing inserted anchor text,
  7704.                 //   so disable control after 1st insert
  7705.                 (GetDlgItem(IDC_HREF_UNLINK))->EnableWindow(FALSE);
  7706.             } else {
  7707.                 EDT_SetHREFData(m_pMWContext, m_pData);
  7708.             }
  7709.         }
  7710.     }
  7711.  
  7712.     OkToClose();
  7713.     //EDT_EndBatchChanges(m_pMWContext);
  7714. }
  7715.  
  7716. ////////////////////////////////////////////////////////////////
  7717. /*
  7718. // **** TEMPLATE for property pages
  7719. /////////////////////////////////////////////////////////////////////
  7720. CPage::CPage(CWnd* pParent, MWContext * pMWContext,
  7721.                 EDT_<Data> * pData)              // EDT data for this property
  7722.     : CNetscapePropertyPage(CPage::IDD)
  7723. {
  7724.     //{{AFX_DATA_INIT(CPage)
  7725.     //}}AFX_DATA_INIT
  7726.     ASSERT(pMWContext);
  7727. //    ASSERT(pData);
  7728.  
  7729.     m_bActivated = FALSE;
  7730.     m_pMWContext = pMWContext;
  7731.     EDT_<Data> * m_pData;       // EDT data for this property
  7732. }
  7733.  
  7734.  
  7735. void CPage::DoDataExchange(CDataExchange* pDX)
  7736. {
  7737.     CPropertyPage::DoDataExchange(pDX);
  7738.     //{{AFX_DATA_MAP(CPage)
  7739.         // NOTE: the ClassWizard will add DDX and DDV calls here
  7740.     //}}AFX_DATA_MAP
  7741. }
  7742.  
  7743. BEGIN_MESSAGE_MAP(CPage, CNetscapePropertyPage)
  7744.     //{{AFX_MSG_MAP(CPage)
  7745.         // NOTE: the ClassWizard will add message map macros here
  7746.     //}}AFX_MSG_MAP
  7747. END_MESSAGE_MAP()
  7748.  
  7749. BOOL CPage::OnSetActive() 
  7750. {
  7751.     if(!CPropertyPage::OnSetActive())
  7752.         return(FALSE);
  7753.  
  7754.     if(m_bActivated)
  7755.         return(TRUE);
  7756.  
  7757.     // TODO - Fill in controls here
  7758.     m_bActivated = TRUE;
  7759.  
  7760.     // Send data to controls
  7761.     UpdateData(FALSE);
  7762.     return(TRUE);
  7763. }
  7764.  
  7765. void CPage::OnOK() 
  7766. {
  7767.  
  7768.     CPropertyPage::OnOK();
  7769.  
  7770.     // never visited this page so don't bother
  7771.     if(!m_bActivated)
  7772.         return;
  7773.  
  7774.     // TODO - Get control data back into pData here
  7775. }
  7776. */
  7777. #endif // EDITOR
  7778.