home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / compmisc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  14.7 KB  |  558 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. /* COMPMISC.CPP - Contains controls which are utilized in the compose
  20.  * window address/attachment block.  Also contains the resizer control
  21.  * which resizes the text edit control
  22.  */
  23.  
  24. #include "stdafx.h"
  25. #include "compmisc.h"
  26. #include "compfrm.h"
  27. #include "compbar.h"
  28. #include "findrepl.h"
  29. #include "spellcli.h"       // spell checker client
  30. #include "prefapi.h"
  31.  
  32. #ifdef XP_WIN32
  33. #define EDIT_CONTROL_BUFFER_SIZE    UINT_MAX
  34. #else
  35. #define EDIT_CONTROL_BUFFER_SIZE    ((UINT)(32*1024))
  36. #endif
  37.  
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CBlankWnd - resizes the edit control and restores focus to the appropriate
  40. //             field.
  41.  
  42. BEGIN_MESSAGE_MAP(CBlankWnd,CWnd)
  43.     ON_EN_CHANGE(IDC_COMPOSEEDITOR,OnChange)
  44.     ON_WM_ERASEBKGND()
  45.     ON_WM_SIZE()
  46.     ON_WM_SETFOCUS()
  47.     ON_WM_PAINT()
  48.     ON_WM_CREATE()
  49.     ON_WM_DESTROY()
  50. END_MESSAGE_MAP()
  51.  
  52. #define INDICATOR_WIDTH 5
  53. #define INDICATOR_COLOR RGB(113,113,255)
  54.  
  55. PR_CALLBACK PrefSetWrapCol(const char *pPref, void *pData)
  56. {
  57.     int32 iCol;
  58.     PREF_GetIntPref("mailnews.wraplength", &iCol);
  59.  
  60.     CBlankWnd * pEditorWindow = (CBlankWnd *)pData;
  61.     pEditorWindow->SetWrapCol(iCol);
  62.     pEditorWindow->Invalidate(TRUE);// must pass TRUE
  63. }
  64.  
  65. int CBlankWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  66. {
  67.     if (CWnd::OnCreate(lpCreateStruct) == -1)
  68.         return -1;
  69.  
  70.     m_lWrapCol = 0L;
  71.  
  72.     //register call back for wrap long line
  73.     PREF_RegisterCallback("mailnews.wraplength", PrefSetWrapCol, (void *)this);
  74.     PREF_GetIntPref("mailnews.wraplength",&m_lWrapCol);
  75.     return 0;
  76. }
  77.  
  78. void CBlankWnd::OnDestroy()
  79. {
  80.     PREF_UnregisterCallback("mailnews.wraplength", PrefSetWrapCol, this);
  81.     CWnd::OnDestroy();
  82. }
  83.  
  84. void CBlankWnd::OnPaint()
  85. {
  86.    CPaintDC dc(this);
  87.    CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  88.    if (pFrame->GetWrapLongLines())
  89.    {
  90.        CRect rect;
  91.        GetClientRect(rect);
  92.        int iPos = ((int)GetWrapCol()) * pFrame->GetCharWidth();
  93.        if (iPos < rect.Width())
  94.        {
  95.            CPen pen(PS_SOLID,1,INDICATOR_COLOR);
  96.            CPen * pOldPen = dc.SelectObject(&pen);
  97.            iPos -= (INDICATOR_WIDTH/2);
  98.            dc.MoveTo(iPos,1);
  99.            dc.LineTo(iPos+INDICATOR_WIDTH,1);
  100.            dc.MoveTo(iPos+1,2);
  101.            dc.LineTo((iPos+INDICATOR_WIDTH)-1,2);
  102.            dc.SetPixel(iPos+2,3,INDICATOR_COLOR);
  103.            dc.SelectObject(pOldPen);
  104.        }
  105.    }
  106. }
  107.  
  108. void CBlankWnd::OnSetFocus(CWnd *)
  109. {
  110.     // when focus is given to this window... focus is passed off to the
  111.     // last field which had focus.
  112.     CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  113.     if (pFrame->GetFocusField() && IsWindow(pFrame->GetFocusField()->m_hWnd))
  114.         pFrame->GetFocusField()->SetFocus();
  115. }
  116.  
  117. void CBlankWnd::OnChange(void)
  118. {   
  119.     // the backend should be notified that the text has been 
  120.     // changed  whener an edit occurs
  121.     CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  122.     m_bModified = TRUE;
  123. }
  124.  
  125. BOOL CBlankWnd::OnEraseBkgnd (CDC * pdc)
  126. {
  127.     // erase the background with the default brush
  128.     CRect rect;
  129.     CBrush Brush(GetSysColor(COLOR_WINDOW));
  130.     GetClientRect (&rect);
  131.     pdc->FillRect (rect, &Brush);
  132.     return TRUE;
  133. }
  134.  
  135. void CBlankWnd::OnSize ( UINT nType, int cx, int cy )
  136. {
  137.     // resize the editor whenver this window is resized.
  138.     // a border is given on the left so that the cursor doesn't
  139.     // but right up against the edge (looks bad)
  140.     CWnd::OnSize ( nType, cx, cy );    
  141.     CRect rect ( EDIT_MARGIN_OFFSET, EDIT_TOP_MARGIN, cx, cy ); 
  142.     CComposeFrame * pFrame = (CComposeFrame*)GetParent()->GetParent();
  143.     if (IsWindow(pFrame->GetEditor()->m_hWnd))
  144.         pFrame->GetEditor()->MoveWindow ( rect );
  145. }
  146.  
  147. /////////////////////////////////////////////////////////////////////////////
  148. // CComposeEdit - This is the regular text edit control. This is probably
  149. //
  150.  
  151. BEGIN_MESSAGE_MAP(CComposeEdit, CGenericEdit)
  152.    ON_WM_KEYDOWN()
  153.    ON_WM_CREATE()
  154.    ON_WM_SETFOCUS()
  155.    ON_COMMAND(ID_CHECK_SPELLING, OnCheckSpelling)
  156.    // edit menu
  157.    ON_COMMAND(ID_EDIT_CUT,OnCut)
  158.    ON_COMMAND(ID_EDIT_COPY,OnCopy)
  159.    ON_COMMAND(ID_EDIT_PASTE,OnPaste)
  160.    ON_COMMAND(ID_EDIT_UNDO,OnUndo)
  161.    ON_COMMAND(idm_redo,OnRedo)
  162.    ON_COMMAND(ID_EDIT_DELETE,OnDelete)
  163.    ON_COMMAND(IDM_SELECTALL,OnSelectAll)
  164.    ON_COMMAND(IDM_FINDAGAIN,OnFindAgain)
  165.    ON_COMMAND(IDM_FINDINMESSAGE,OnFindInMessage)
  166.    ON_REGISTERED_MESSAGE(WM_FINDREPLACE, OnFindReplace)
  167.    ON_UPDATE_COMMAND_UI(ID_EDIT_CUT,OnUpdateCut)
  168.    ON_UPDATE_COMMAND_UI(ID_EDIT_COPY,OnUpdateCopy)
  169.    ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE,OnUpdatePaste)
  170.    ON_UPDATE_COMMAND_UI(IDM_PASTEASQUOTE,OnUpdatePasteAsQuote)
  171.    ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO,OnUpdateUndo)
  172.    ON_UPDATE_COMMAND_UI(ID_EDIT_DELETE,OnUpdateDelete)
  173.    ON_UPDATE_COMMAND_UI(IDM_SELECTALL,OnUpdateSelectAll)
  174.    ON_UPDATE_COMMAND_UI(IDM_FINDINMESSAGE,OnUpdateFindInMessage)
  175.    ON_UPDATE_COMMAND_UI(IDM_FINDAGAIN,OnUpdateFindAgain)
  176. END_MESSAGE_MAP()
  177.  
  178. CComposeEdit::CComposeEdit(CComposeFrame * pFrame)
  179. {
  180.     m_pComposeFrame = pFrame;
  181.     m_cxChar = 1;
  182. #ifdef XP_WIN16
  183.     // win16 edit control's memory is by default, allocated from the heap.. which is
  184.     // usually not enough.... so create a 32K message buffer
  185.     m_hTextElementSegment = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, EDIT_CONTROL_BUFFER_SIZE); 
  186. #endif
  187. }
  188.  
  189. CComposeEdit::~CComposeEdit()
  190. {
  191. #ifdef XP_WIN16
  192.     // free up the 16bit memory buffer
  193.     if (m_hTextElementSegment)
  194.         GlobalFree(m_hTextElementSegment);
  195. #endif
  196. }
  197.  
  198. #ifdef XP_WIN16
  199. //
  200. // The creator of this form element should have created a segment for
  201. // us to live in before we got here.  Tell Windows to use that 
  202. // segment rather than the application's so that we don't run out of
  203. // DGROUP space
  204. //
  205. BOOL CComposeEdit::PreCreateWindow( CREATESTRUCT& cs )
  206. {
  207.     // during a precreate in happy 16bit land, lock the edit data
  208.     // buffer and tell the control to use it.
  209.     if (CGenericEdit::PreCreateWindow(cs)) {
  210.  
  211.         ASSERT(m_hTextElementSegment);
  212.  
  213.         if(!m_hTextElementSegment)
  214.             return TRUE;
  215.  
  216.         LPVOID lpEditDC = (LPVOID) GlobalLock(m_hTextElementSegment);
  217.  
  218.         if (lpEditDC) {
  219.             UINT uSegment = HIWORD((LONG) lpEditDC);
  220.             if (LocalInit((UINT)uSegment,0,(WORD)(GlobalSize(m_hTextElementSegment)-16))) {
  221.                 cs.hInstance = (HINSTANCE) uSegment;
  222.                 UnlockSegment(uSegment);
  223.             }
  224.             else 
  225.                 GlobalUnlock(m_hTextElementSegment);
  226.  
  227.         }
  228.         return TRUE;
  229.     }
  230.  
  231.     return FALSE;   
  232. }
  233. #endif  
  234.  
  235. void CComposeEdit::OnSetFocus(CWnd * pWnd)
  236. {
  237.     // When focus is set to the edit field, tell the parent
  238.     CGenericEdit::OnSetFocus(pWnd);
  239.     CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  240.     pFrame->SetFocusField(this);
  241. }
  242.  
  243. int CComposeEdit::OnCreate ( LPCREATESTRUCT lpcs )
  244. {
  245.     // set up the fonts, get the character size
  246.     int iRet = CGenericEdit::OnCreate ( lpcs );
  247.  
  248.     LimitText(EDIT_CONTROL_BUFFER_SIZE);
  249.     
  250.     CClientDC dc ( this );
  251.     LOGFONT lf;
  252.     XP_MEMSET(&lf,0,sizeof(LOGFONT));
  253.     CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  254.     lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH;
  255.         strcpy(lf.lfFaceName, IntlGetUIFixFaceName(pFrame->m_iCSID));
  256.     lf.lfCharSet = IntlGetLfCharset(pFrame->m_iCSID); 
  257.     lf.lfHeight = -MulDiv(9,dc.GetDeviceCaps(LOGPIXELSY), 72);
  258.     lf.lfQuality = PROOF_QUALITY;
  259.     
  260.     if (m_cfRegFont) {
  261.         theApp.ReleaseAppFont(m_cfRegFont);
  262.     }
  263.     m_cfRegFont = theApp.CreateAppFont( lf );
  264.  
  265.     TEXTMETRIC tm;
  266.     CFont * pOldFont = dc.SelectObject(CFont::FromHandle(m_cfRegFont));
  267.     dc.GetTextMetrics(&tm);
  268.     dc.SelectObject(pOldFont);
  269.     m_cxChar = tm.tmAveCharWidth;
  270.     ::SendMessage(GetSafeHwnd(), WM_SETFONT, (WPARAM)m_cfRegFont, FALSE);
  271.  
  272.     return iRet;
  273. }
  274.  
  275. void CComposeEdit::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
  276. {
  277.     // process the tab key so that it properly tabs between the
  278.     // address block and the editor.
  279.     if ((nChar==VK_TAB)&&(GetKeyState(VK_SHIFT)&0x8000)) {
  280.         CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  281.         MSG msg;
  282.         while (PeekMessage(&msg,m_hWnd,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE))
  283.             ;
  284.         CComposeBar * pBar = pFrame->GetComposeBar();
  285.         ASSERT(pBar);        
  286.         if (pBar)
  287.             pBar->m_pSubjectEdit->SetFocus();
  288.     }
  289.     else
  290.     {
  291.         CGenericEdit::OnKeyDown(nChar,nRepCnt,nFlags);
  292.     }
  293. }
  294.  
  295. void CComposeEdit::OnCheckSpelling()
  296. {
  297.     CPlainTextSpellChecker SpellChecker(this);
  298.  
  299.     if (SpellChecker.ProcessDocument() != 0)
  300.         ASSERT(FALSE);
  301. }
  302.  
  303. void CComposeEdit::OnCut()
  304. {
  305.     Cut();
  306. }
  307.  
  308. void CComposeEdit::OnCopy()
  309. {
  310.     Copy();
  311. }
  312.  
  313. void CComposeEdit::OnPaste()
  314. {
  315.    Paste();
  316. }
  317.  
  318. void CComposeEdit::OnUndo()
  319. {
  320.     Undo();
  321. }
  322.  
  323. void CComposeEdit::OnRedo()
  324. {
  325. }
  326.  
  327. void CComposeEdit::OnDelete()
  328. {
  329.     if (GetFocus() == this)
  330.         Clear();
  331. }
  332.  
  333. void CComposeEdit::OnFindInMessage()
  334. {
  335.     CNetscapeFindReplaceDialog *dlg;
  336.     dlg = new CNetscapeFindReplaceDialog();
  337.     dlg->Create(TRUE, 
  338.         theApp.m_csFindString, 
  339.         NULL, 
  340.         FR_DOWN | FR_NOWHOLEWORD | FR_HIDEWHOLEWORD | FR_NOUPDOWN, 
  341.         GetParentFrame());
  342. }
  343.  
  344. void CComposeEdit::OnFindAgain()
  345. {
  346.    FindText();
  347. }
  348.  
  349. void CComposeEdit::OnUpdateCut(CCmdUI * pCmdUI)
  350. {
  351.    if (GetFocus() == this)
  352.       pCmdUI->Enable(IsSelection());
  353. }
  354.  
  355. void CComposeEdit::OnUpdateCopy(CCmdUI * pCmdUI)
  356. {
  357.    if (GetFocus() == this)
  358.        pCmdUI->Enable(IsSelection());
  359. }
  360.  
  361. void CComposeEdit::OnUpdatePaste(CCmdUI * pCmdUI)
  362. {
  363.    if (GetFocus() == this)
  364.       pCmdUI->Enable(IsClipboardData());
  365. }
  366.  
  367. BOOL CComposeEdit::IsSelection()
  368. {
  369.     int nStart, nEnd;
  370.     GetSel(nStart,nEnd);
  371.     return ((nEnd-nStart)>0);
  372. }
  373.  
  374. BOOL CComposeEdit::IsClipboardData()
  375. {
  376.     BOOL retVal = FALSE;
  377.     OpenClipboard();
  378.             
  379.     if (GetClipboardData(CF_TEXT)) {
  380.         retVal = TRUE;
  381.     }
  382.     CloseClipboard();
  383.     return retVal;
  384. }
  385.  
  386. void CComposeEdit::OnUpdatePasteAsQuote(CCmdUI * pCmdUI)
  387. {
  388.     if (GetFocus() == this)
  389.        pCmdUI->Enable(IsClipboardData());
  390. }
  391.  
  392. void CComposeEdit::OnUpdateUndo(CCmdUI * pCmdUI)
  393. {
  394.     if (GetFocus() == this)
  395.        pCmdUI->Enable(CanUndo());
  396. }
  397.  
  398. void CComposeEdit::OnUpdateDelete(CCmdUI * pCmdUI)
  399. {
  400.     if (GetFocus() == this)
  401.         pCmdUI->Enable(IsSelection());
  402. }
  403.  
  404. void CComposeEdit::OnUpdateFindInMessage(CCmdUI * pCmdUI)
  405. {
  406.    if ( GetWindowTextLength() > 0 && (GetFocus() == this))
  407.       pCmdUI->Enable(TRUE);
  408.    else
  409.       pCmdUI->Enable(FALSE);
  410. }
  411.  
  412. void CComposeEdit::OnUpdateFindAgain(CCmdUI * pCmdUI)
  413. {
  414.    if ((theApp.m_csFindString && strlen(theApp.m_csFindString)) && (GetFocus() == this))
  415.       pCmdUI->Enable(TRUE);
  416.    else
  417.       pCmdUI->Enable(FALSE);
  418. }
  419.  
  420. void CComposeEdit::OnSelectAll()
  421. {
  422.     SetSel(0,-1);
  423.     SetFocus();
  424. }
  425.  
  426. void CComposeEdit::OnUpdateSelectAll(CCmdUI *pCmdUI)
  427. {
  428.     pCmdUI->Enable(TRUE);
  429. }
  430.  
  431. BEGIN_MESSAGE_MAP(CComposeSubjectEdit, CGenericEdit)
  432.     ON_WM_SETFOCUS()
  433.     ON_WM_KILLFOCUS()
  434. END_MESSAGE_MAP()
  435.  
  436. void CComposeSubjectEdit::OnSetFocus(CWnd * pWnd)
  437. {
  438.     // When focus is set to the edit field, tell the parent
  439.     CGenericEdit::OnSetFocus(pWnd);
  440.     CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  441.     pFrame->SetFocusField(this);
  442. }
  443.  
  444. void CComposeSubjectEdit::OnKillFocus(CWnd * pWnd)
  445. {
  446.    CGenericEdit::OnKillFocus(pWnd);
  447.    CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  448.    CString cs;
  449.    GetWindowText(cs);
  450.    if (cs.GetLength())
  451.        pFrame->GetChrome()->SetDocumentTitle(cs);
  452. }
  453.  
  454. BOOL CComposeSubjectEdit::PreTranslateMessage(MSG* pMsg)
  455. {
  456.    if (pMsg->message == WM_KEYDOWN)
  457.    {
  458.       if (pMsg->wParam == VK_RETURN)
  459.         {
  460.          CComposeFrame * pFrame = (CComposeFrame*)GetParentFrame();
  461.          pFrame->GetComposeBar()->TabControl(FALSE,FALSE,this);
  462.          return TRUE;
  463.       }
  464.  
  465.       if (pMsg->wParam == 'v' || pMsg->wParam == 'V')
  466.       {
  467.          if (GetKeyState(VK_CONTROL)&0x8000)
  468.          {
  469.             Paste();
  470.             return TRUE;
  471.          }
  472.       } 
  473.       else if (pMsg->wParam == VK_INSERT)
  474.       {
  475.          if (GetKeyState(VK_SHIFT)&0x8000)
  476.          {
  477.             Paste();
  478.             return TRUE;
  479.          }
  480.          else if (GetKeyState(VK_CONTROL)&0x8000)
  481.          {
  482.             Copy();
  483.             return TRUE;
  484.          }
  485.       }
  486.       else if (pMsg->wParam == 'x' || pMsg->wParam == 'X')
  487.       {
  488.          if (GetKeyState(VK_CONTROL)&0x8000)
  489.          {
  490.             Cut();
  491.             return TRUE;
  492.          }
  493.       } 
  494.       else if (pMsg->wParam == 'c' || pMsg->wParam == 'C')
  495.       {
  496.          if (GetKeyState(VK_CONTROL)&0x8000)
  497.          {
  498.             Copy();
  499.             return TRUE;
  500.          }
  501.       } 
  502.    }
  503.    return CEdit::PreTranslateMessage(pMsg);
  504. }
  505.  
  506. LRESULT CComposeEdit::OnFindReplace(WPARAM wParam, LPARAM lParam) 
  507. {
  508.     CFindReplaceDialog * dlg = ::CFindReplaceDialog::GetNotifier(lParam);
  509.     if (!dlg) 
  510.         return NULL;
  511.       
  512.     FINDREPLACE findstruct = dlg->m_fr;
  513.         
  514.     if (dlg->IsTerminating()) {
  515.         return NULL;
  516.     }     
  517.  
  518.     // Something wrong or user cancelled dialog box
  519.     if(!(findstruct.Flags & FR_FINDNEXT))
  520.         return NULL;
  521.           
  522.     // remember this string for next time
  523.     theApp.m_csFindString = findstruct.lpstrFindWhat;
  524.     theApp.m_csReplaceString = findstruct.lpstrReplaceWith;
  525.     theApp.m_bMatchCase   = dlg->MatchCase();
  526.     theApp.m_bSearchDown  = dlg->SearchDown(); 
  527.  
  528.    return (LRESULT) FindText();
  529. }
  530.  
  531. BOOL CComposeEdit::FindText()
  532. {
  533.    CString cs, csSearch = theApp.m_csFindString;
  534.    GetWindowText(cs);
  535.  
  536.    int nStart, nEnd;
  537.    GetSel(nStart,nEnd);
  538.  
  539.    if (!theApp.m_bMatchCase)
  540.    {
  541.       cs.MakeLower();
  542.       csSearch.MakeLower();
  543.    }
  544.    if (!cs.IsEmpty())
  545.    {
  546.       int ipos = nEnd;
  547.       int ipos2;
  548.       LPCSTR lpcstr = cs;
  549.       if ((ipos2 = CString(&lpcstr[ipos]).Find(csSearch)) != -1)
  550.       {
  551.          SetSel(ipos + ipos2, ipos + ipos2 + strlen(csSearch));
  552.           return(TRUE);
  553.       }
  554.    }
  555.    return FALSE;
  556. }
  557.  
  558.