Index: Color.cpp =================================================================== RCS file: /cvs/mushclient/Color.cpp,v retrieving revision 1.2 retrieving revision 1.4 diff -c -r1.2 -r1.4 *** Color.cpp 12 Apr 2002 05:01:04 -0000 1.2 --- Color.cpp 5 Aug 2008 06:25:12 -0000 1.4 *************** *** 13,18 **** --- 13,19 ---- #include "StdAfx.h" #include "Color.h" + #include #ifdef _DEBUG //#define new DEBUG_NEW *************** *** 45,79 **** { ASSERT(0 <= red && red <= 255); ToRGB(); ! m_color[c_red] = static_cast(red); ! m_bIsHLS = false; } void CColor::SetGreen(int green) { ASSERT(0 <= green && green <= 255); ToRGB(); ! m_color[c_green] = static_cast(green); ! m_bIsHLS = false; } void CColor::SetBlue(int blue) { ASSERT(0 <= blue && blue <= 255); ToRGB(); ! m_color[c_blue] = static_cast(blue); ! m_bIsHLS = false; } ! void CColor::SetRGB(int red, int blue, int green) { ASSERT(0 <= red && red <= 255); ASSERT(0 <= green && green <= 255); ASSERT(0 <= blue && blue <= 255); - m_color[c_red] = static_cast(red); - m_color[c_green] = static_cast(green); - m_color[c_blue] = static_cast(blue); m_bIsHLS = false; m_bIsRGB = true; } --- 46,75 ---- { ASSERT(0 <= red && red <= 255); ToRGB(); ! m_colorref = RGB (red, GetGValue(m_colorref), GetBValue(m_colorref)); } void CColor::SetGreen(int green) { ASSERT(0 <= green && green <= 255); ToRGB(); ! m_colorref = RGB (GetRValue(m_colorref), green, GetBValue(m_colorref)); } void CColor::SetBlue(int blue) { ASSERT(0 <= blue && blue <= 255); ToRGB(); ! m_colorref = RGB (GetRValue(m_colorref), GetGValue(m_colorref), blue); } ! void CColor::SetRGB(int red, int green, int blue) { ASSERT(0 <= red && red <= 255); ASSERT(0 <= green && green <= 255); ASSERT(0 <= blue && blue <= 255); + m_colorref = RGB (red, green, blue); m_bIsHLS = false; m_bIsRGB = true; } *************** *** 81,131 **** int CColor::GetRed() const { const_cast(this)->ToRGB(); ! return m_color[c_red]; } int CColor::GetGreen() const { const_cast(this)->ToRGB(); ! return m_color[c_green]; } int CColor::GetBlue() const { const_cast(this)->ToRGB(); ! return m_color[c_blue]; } // HSL ! void CColor::SetHue(float hue) { ASSERT(hue >= 0.0 && hue <= 360.0); ToHLS(); m_hue = hue; - m_bIsRGB = false; } ! void CColor::SetSaturation(float saturation) { ASSERT(saturation >= 0.0 && saturation <= 1.0); // 0.0 ist undefiniert ToHLS(); m_saturation = saturation; - m_bIsRGB = false; } ! void CColor::SetLuminance(float luminance) { ASSERT(luminance >= 0.0 && luminance <= 1.0); ToHLS(); m_luminance = luminance; - m_bIsRGB = false; } ! void CColor::SetHLS(float hue, float luminance, float saturation) { ASSERT(hue >= 0.0 && hue <= 360.0); ASSERT(luminance >= 0.0 && luminance <= 1.0); --- 77,124 ---- int CColor::GetRed() const { const_cast(this)->ToRGB(); ! return GetRValue(m_colorref); } int CColor::GetGreen() const { const_cast(this)->ToRGB(); ! return GetGValue(m_colorref); } int CColor::GetBlue() const { const_cast(this)->ToRGB(); ! return GetBValue(m_colorref); } // HSL ! void CColor::SetHue(double hue) { ASSERT(hue >= 0.0 && hue <= 360.0); ToHLS(); m_hue = hue; } ! void CColor::SetSaturation(double saturation) { ASSERT(saturation >= 0.0 && saturation <= 1.0); // 0.0 ist undefiniert ToHLS(); m_saturation = saturation; } ! void CColor::SetLuminance(double luminance) { ASSERT(luminance >= 0.0 && luminance <= 1.0); ToHLS(); m_luminance = luminance; } ! void CColor::SetHLS(double hue, double luminance, double saturation) { ASSERT(hue >= 0.0 && hue <= 360.0); ASSERT(luminance >= 0.0 && luminance <= 1.0); *************** *** 138,257 **** m_bIsHLS = true; } ! float CColor::GetHue() const { const_cast(this)->ToHLS(); return m_hue; } ! float CColor::GetSaturation() const { const_cast(this)->ToHLS(); return m_saturation; } ! float CColor::GetLuminance() const { const_cast(this)->ToHLS(); return m_luminance; } ! // Konvertierung void CColor::ToHLS() { ! if (!m_bIsHLS) ! { ! // Konvertierung ! unsigned char minval = min(m_color[c_red], min(m_color[c_green], m_color[c_blue])); ! unsigned char maxval = max(m_color[c_red], max(m_color[c_green], m_color[c_blue])); ! float mdiff = float(maxval) - float(minval); ! float msum = float(maxval) + float(minval); ! ! m_luminance = msum / 510.0f; ! if (maxval == minval) { ! m_saturation = 0.0f; ! m_hue = 0.0f; ! } ! else ! { ! float rnorm = (maxval - m_color[c_red] ) / mdiff; ! float gnorm = (maxval - m_color[c_green]) / mdiff; ! float bnorm = (maxval - m_color[c_blue] ) / mdiff; ! ! m_saturation = (m_luminance <= 0.5f) ? (mdiff / msum) : (mdiff / (510.0f - msum)); ! ! if (m_color[c_red] == maxval) m_hue = 60.0f * (6.0f + bnorm - gnorm); ! if (m_color[c_green] == maxval) m_hue = 60.0f * (2.0f + rnorm - bnorm); ! if (m_color[c_blue] == maxval) m_hue = 60.0f * (4.0f + gnorm - rnorm); ! if (m_hue > 360.0f) m_hue = m_hue - 360.0f; } ! m_bIsHLS = true; ! } } void CColor::ToRGB() { ! if (!m_bIsRGB) ! { ! if (m_saturation == 0.0) // Grauton, einfacher Fall ! { ! m_color[c_red] = m_color[c_green] = m_color[c_blue] = unsigned char(m_luminance * 255.0); ! } ! else { ! float rm1, rm2; ! ! if (m_luminance <= 0.5f) rm2 = m_luminance + m_luminance * m_saturation; ! else rm2 = m_luminance + m_saturation - m_luminance * m_saturation; ! rm1 = 2.0f * m_luminance - rm2; ! m_color[c_red] = ToRGB1(rm1, rm2, m_hue + 120.0f); ! m_color[c_green] = ToRGB1(rm1, rm2, m_hue); ! m_color[c_blue] = ToRGB1(rm1, rm2, m_hue - 120.0f); } - m_bIsRGB = true; - } - } ! unsigned char CColor::ToRGB1(float rm1, float rm2, float rh) ! { ! if (rh > 360.0f) rh -= 360.0f; ! else if (rh < 0.0f) rh += 360.0f; ! ! if (rh < 60.0f) rm1 = rm1 + (rm2 - rm1) * rh / 60.0f; ! else if (rh < 180.0f) rm1 = rm2; ! else if (rh < 240.0f) rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f; ! ! return static_cast(rm1 * 255); ! } ! // Stringkonvertierung im Format RRGGBB - CString CColor::GetString() const - { - CString color; - color.Format("%02X%02X%02X", GetRed(), GetGreen(), GetBlue()); - return color; } ! bool CColor::SetString(LPCTSTR pcColor) ! { ! ASSERT(pcColor); ! int r, g, b; ! if (sscanf(pcColor, "%2x%2x%2x", &r, &g, &b) != 3) ! { ! m_color[c_red] = m_color[c_green] = m_color[c_blue] = 0; ! return false; ! } ! else { ! m_color[c_red] = static_cast(r); ! m_color[c_green] = static_cast(g); ! m_color[c_blue] = static_cast(b); ! m_bIsRGB = true; ! m_bIsHLS = false; ! return true; } ! } --- 131,280 ---- m_bIsHLS = true; } ! double CColor::GetHue() const { const_cast(this)->ToHLS(); return m_hue; } ! double CColor::GetSaturation() const { const_cast(this)->ToHLS(); return m_saturation; } ! double CColor::GetLuminance() const { const_cast(this)->ToHLS(); return m_luminance; } ! // see: http://en.wikipedia.org/wiki/HSL_color_space void CColor::ToHLS() { ! if (m_bIsHLS) ! return; ! m_bIsHLS = true; // well it will be soon ;) ! m_bIsRGB = false; ! ! //Convert rgb values to the range 0-1 ! double R = ((double) GetRValue (m_colorref)) / 255.0; ! double G = ((double) GetGValue (m_colorref)) / 255.0; ! double B = ((double) GetBValue (m_colorref)) / 255.0; ! ! //Find min and max values of R,G,B ! double mincolor = min (R, min (G, B)); ! double maxcolor = max (R, max (G, B)); ! ! double colordiff = maxcolor - mincolor; ! ! //Special treatment for grey colors ! if (colordiff == 0.0) { ! m_hue = m_saturation = 0.0; ! m_luminance = mincolor; // L = 1/2 (min + max) so in this case, min or max ! return; } ! ! m_luminance = (maxcolor + mincolor) / 2.0; // L = 1/2 (min + max) ! ! if (m_luminance < 0.5) ! m_saturation = colordiff / (maxcolor + mincolor); ! else ! m_saturation = colordiff / (2.0 - (maxcolor + mincolor)); ! ! if (R == maxcolor) ! m_hue = 60.0 * (G - B) / colordiff + 0.0; ! else if (G == maxcolor) ! m_hue = 60.0 * (B - R) / colordiff + 120.0; ! else ! m_hue = 60.0 * (R - G) / colordiff + 240.0; ! ! if (m_hue < 0.0) ! m_hue += 360.0; ! else if (m_hue > 360.0) ! m_hue -= 360.0; ! ! if (m_saturation > 1.0) ! m_saturation = 1.0; ! else if (m_saturation < 0.0) ! m_saturation = 0.0; } + // see: http://en.wikipedia.org/wiki/HSL_color_space + void CColor::ToRGB() { ! ! if (m_bIsRGB) ! return; ! ! m_bIsRGB = true; // well it will be soon ;) ! m_bIsHLS = false; ! ! ! if (m_saturation <= 0.0) { ! // round up ! m_colorref = RGB (m_luminance * 255 + 0.5, m_luminance * 255 + 0.5, m_luminance * 255 + 0.5); ! return; } ! double q; ! if (m_luminance < 0.5) ! q = m_luminance * (1.0 + m_saturation); ! else ! q = (m_luminance + m_saturation) - (m_luminance * m_saturation); ! ! double p = 2.0 * m_luminance - q; ! double hk = m_hue / 360.0; ! ! double tr = hk + 1.0 / 3.0; // red ! double tg = hk; // green ! double tb = hk - 1.0 / 3.0; // blue ! ! // ensure not < 0 ! tr = (tr < 0.0) ? tr + 1.0 : tr; ! tg = (tg < 0.0) ? tg + 1.0 : tg; ! tb = (tb < 0.0) ? tb + 1.0 : tb; ! ! // ensure not > 1 ! tr = (tr > 1.0) ? tr - 1.0 : tr; ! tg = (tg > 1.0) ? tg - 1.0 : tg; ! tb = (tb > 1.0) ? tb - 1.0 : tb; ! ! ! double r, g, b; ! ! r = ToRGB1 (tr, p, q) * 255; ! g = ToRGB1 (tg, p, q) * 255; ! b = ToRGB1 (tb, p, q) * 255; ! ! // ASSERT (0 <= r && r <= 255); ! // ASSERT (0 <= g && g <= 255); ! // ASSERT (0 <= b && b <= 255); ! ! ! m_colorref = RGB (r + 0.5, g + 0.5, b + 0.5); } ! ! double CColor::ToRGB1 (double t, double p, double q) { ! if (t < (1.0 / 6.0)) ! return p + ((q - p) * 6.0 * t); ! ! if (t < 0.5) ! return q; ! ! if (t < (2.0 / 3.0)) ! return p + ((q - p) * 6.0 * (2.0 / 3.0 - t)); ! ! return p; ! } ! Index: Color.h =================================================================== RCS file: /cvs/mushclient/Color.h,v retrieving revision 1.1 retrieving revision 1.2 diff -c -r1.1 -r1.2 *** Color.h 12 Apr 2002 01:13:41 -0000 1.1 --- Color.h 2 Aug 2008 06:35:23 -0000 1.2 *************** *** 28,34 **** void SetRed(int red); // 0..255 void SetGreen(int green); // 0..255 void SetBlue(int blue); // 0..255 ! void SetRGB(int red, int blue, int green); void SetColor(COLORREF cr = 0); int GetRed() const; // 0..255 --- 28,34 ---- void SetRed(int red); // 0..255 void SetGreen(int green); // 0..255 void SetBlue(int blue); // 0..255 ! void SetRGB(int red, int green, int blue); void SetColor(COLORREF cr = 0); int GetRed() const; // 0..255 *************** *** 37,88 **** // HLS - Routinen // -------------- ! void SetHue(float hue); // 0.0 .. 360.0 ! void SetLuminance(float luminance); // 0.0 .. 1.0 ! void SetSaturation(float saturation); // 0.0 .. 1.0 ! void SetHLS(float hue, float luminance, float saturation); ! ! float GetHue() const; // 0.0 .. 360.0 ! float GetLuminance() const; // 0.0 .. 1.0 ! float GetSaturation() const; // 0.0 .. 1.0 ! ! // String Konvertierung ! // --------------------- ! CString GetString() const; // Liefert String im Format RRGGBB ! bool SetString(LPCTSTR pcColor); // Erwartet String im Format RRGGBB private: // Konvertierung // ------------- ! void ToRGB(); // logisch konstant, nicht physikalisch ! void ToHLS(); // logisch konstant, nicht physikalisch ! static unsigned char ToRGB1(float rm1, float rm2, float rh); ! ! // Daten ! // ----- ! union // Byteweiser Zugriff auf die COLORREF Struktur ! { ! COLORREF m_colorref; ! unsigned char m_color[4]; ! }; ! enum {c_red = 0, c_green = 1, c_blue = 2, c_null = 3}; // enum Hack für colorbyte-Index ! ! float m_hue; // 0.0 .. 360.0 // Winkel ! float m_saturation; // 0.0 .. 1.0 // Prozent ! float m_luminance; // 0.0 .. 1.0 // Prozent ! // Flag für Lazy Evaluation bool m_bIsRGB; bool m_bIsHLS; - // statische Konstanten für benannte Farben - struct DNamedColor - { - COLORREF color; - LPCTSTR name; - }; }; #endif --- 37,76 ---- // HLS - Routinen // -------------- ! void SetHue(double hue); // 0.0 .. 360.0 ! void SetLuminance(double luminance); // 0.0 .. 1.0 ! void SetSaturation(double saturation); // 0.0 .. 1.0 ! void SetHLS(double hue, double luminance, double saturation); ! ! double GetHue() const; // 0.0 .. 360.0 ! double GetLuminance() const; // 0.0 .. 1.0 ! double GetSaturation() const; // 0.0 .. 1.0 private: // Konvertierung // ------------- ! void ToRGB(); ! void ToHLS(); ! /* ! static unsigned char ToRGB1(double rm1, double rm2, double rh); ! ! */ ! ! static double ToRGB1(double t, double p, double q); ! ! COLORREF m_colorref; ! ! double m_hue; // 0.0 .. 360.0 // Winkel ! double m_saturation; // 0.0 .. 1.0 // Prozent ! double m_luminance; // 0.0 .. 1.0 // Prozent ! ! // Flag for lazy evaluation bool m_bIsRGB; bool m_bIsHLS; }; #endif Index: MUSHclient.rc =================================================================== RCS file: /cvs/mushclient/MUSHclient.rc,v retrieving revision 1.225 retrieving revision 1.227 diff -c -r1.225 -r1.227 *** MUSHclient.rc 15 Jul 2008 06:15:32 -0000 1.225 --- MUSHclient.rc 6 Aug 2008 02:35:17 -0000 1.227 *************** *** 75,82 **** // VS_VERSION_INFO VERSIONINFO ! FILEVERSION 4,0,34,0 ! PRODUCTVERSION 4,0,34,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L --- 75,82 ---- // VS_VERSION_INFO VERSIONINFO ! FILEVERSION 4,0,35,0 ! PRODUCTVERSION 4,0,35,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L *************** *** 94,107 **** VALUE "Comments", "MUSHclient - a client program for playing MUD games\0" VALUE "CompanyName", "Gammon Software Solutions\0" VALUE "FileDescription", "MUSHclient\0" ! VALUE "FileVersion", "4.34\0" VALUE "InternalName", "MUSHCLIENT\0" VALUE "LegalCopyright", "Copyright © 2008 Gammon Software Solutions\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "MUSHCLIENT.EXE\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "MUSHclient\0" ! VALUE "ProductVersion", "4.34\0" VALUE "SpecialBuild", "\0" END END --- 94,107 ---- VALUE "Comments", "MUSHclient - a client program for playing MUD games\0" VALUE "CompanyName", "Gammon Software Solutions\0" VALUE "FileDescription", "MUSHclient\0" ! VALUE "FileVersion", "4.35\0" VALUE "InternalName", "MUSHCLIENT\0" VALUE "LegalCopyright", "Copyright © 2008 Gammon Software Solutions\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "MUSHCLIENT.EXE\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "MUSHclient\0" ! VALUE "ProductVersion", "4.35\0" VALUE "SpecialBuild", "\0" END END Index: OtherTypes.h =================================================================== RCS file: /cvs/mushclient/OtherTypes.h,v retrieving revision 1.94 retrieving revision 1.99 diff -c -r1.94 -r1.99 *** OtherTypes.h 26 Jul 2008 06:13:19 -0000 1.94 --- OtherTypes.h 5 Aug 2008 06:25:12 -0000 1.99 *************** *** 1288,1293 **** --- 1288,1307 ---- long CreateImage(LPCTSTR ImageId, long Row1, long Row2, long Row3, long Row4, long Row5, long Row6, long Row7, long Row8); + long BlendImage(LPCTSTR ImageId, + long Left, long Top, long Right, long Bottom, + short Mode, double Opacity, + long SrcLeft, long SrcTop, long SrcRight, long SrcBottom); + + long ImageFromWindow(LPCTSTR ImageId, CMiniWindow * pSrcWindow); + + long Gradient(long Left, long Top, long Right, long Bottom, + long StartColour, long EndColour, + short Mode); + + long Filter(long Left, long Top, long Right, long Bottom, + short Operation, double Options); + }; typedef map MiniWindowMap; Index: ProcessPreviousLine.cpp =================================================================== RCS file: /cvs/mushclient/ProcessPreviousLine.cpp,v retrieving revision 1.57 retrieving revision 1.58 diff -c -r1.57 -r1.58 *** ProcessPreviousLine.cpp 24 Dec 2007 01:18:05 -0000 1.57 --- ProcessPreviousLine.cpp 30 Jul 2008 22:40:58 -0000 1.58 *************** *** 637,643 **** { CMUSHView* pmyView = (CMUSHView*)pView; ! pmyView->InvalidateLines (iLineCount); } // end of being an output view } // end of doing each view --- 637,643 ---- { CMUSHView* pmyView = (CMUSHView*)pView; ! pmyView->Invalidate (); } // end of being an output view } // end of doing each view Index: doc.cpp =================================================================== RCS file: /cvs/mushclient/doc.cpp,v retrieving revision 1.250 retrieving revision 1.255 diff -c -r1.250 -r1.255 *** doc.cpp 26 Jul 2008 06:13:19 -0000 1.250 --- doc.cpp 5 Aug 2008 06:25:12 -0000 1.255 *************** *** 542,547 **** --- 542,553 ---- DISP_FUNCTION(CMUSHclientDoc, "WindowCreateImage", WindowCreateImage, VT_I4, VTS_BSTR VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4) DISP_FUNCTION(CMUSHclientDoc, "WindowImageOp", WindowImageOp, VT_I4, VTS_BSTR VTS_I2 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_BSTR VTS_I4 VTS_I4) DISP_FUNCTION(CMUSHclientDoc, "WindowFont", WindowFont, VT_I4, VTS_BSTR VTS_BSTR VTS_BSTR VTS_R8 VTS_BOOL VTS_BOOL VTS_BOOL VTS_BOOL VTS_I2 VTS_I2) + DISP_FUNCTION(CMUSHclientDoc, "WindowBlendImage", WindowBlendImage, VT_I4, VTS_BSTR VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I2 VTS_R8 VTS_I4 VTS_I4 VTS_I4 VTS_I4) + DISP_FUNCTION(CMUSHclientDoc, "WindowImageFromWindow", WindowImageFromWindow, VT_I4, VTS_BSTR VTS_BSTR VTS_BSTR) + DISP_FUNCTION(CMUSHclientDoc, "Repaint", Repaint, VT_EMPTY, VTS_NONE) + DISP_FUNCTION(CMUSHclientDoc, "TextRectangle", TextRectangle, VT_I4, VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4) + DISP_FUNCTION(CMUSHclientDoc, "WindowGradient", WindowGradient, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I2) + DISP_FUNCTION(CMUSHclientDoc, "WindowFilter", WindowFilter, VT_I4, VTS_BSTR VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_I2 VTS_R8) DISP_PROPERTY_PARAM(CMUSHclientDoc, "NormalColour", GetNormalColour, SetNormalColour, VT_I4, VTS_I2) DISP_PROPERTY_PARAM(CMUSHclientDoc, "BoldColour", GetBoldColour, SetBoldColour, VT_I4, VTS_I2) DISP_PROPERTY_PARAM(CMUSHclientDoc, "CustomColourText", GetCustomColourText, SetCustomColourText, VT_I4, VTS_I2) Index: doc.h =================================================================== RCS file: /cvs/mushclient/doc.h,v retrieving revision 1.266 retrieving revision 1.271 diff -c -r1.266 -r1.271 *** doc.h 26 Jul 2008 06:13:19 -0000 1.266 --- doc.h 5 Aug 2008 06:25:12 -0000 1.271 *************** *** 21,28 **** // New versions - things to change ! #define THISVERSION 434 // Step 1. ! const CString MUSHCLIENT_VERSION = "4.34"; // Step 2. // Step 3. Don't forget VERSION resource in Resources tab // Step 4. Remember: README.TXT --- 21,28 ---- // New versions - things to change ! #define THISVERSION 435 // Step 1. ! const CString MUSHCLIENT_VERSION = "4.35"; // Step 2. // Step 3. Don't forget VERSION resource in Resources tab // Step 4. Remember: README.TXT *************** *** 1210,1217 **** --- 1210,1228 ---- CBitmap m_ForegroundBitmap; int m_iForegroundMode; + // all our cute little miniwindows MiniWindowMap m_MiniWindows; + + // text rectangle + CRect m_TextRectangle; + long m_TextRectangleBorderOffset, + m_TextRectangleBorderColour, + m_TextRectangleBorderWidth, + m_TextRectangleOutsideFillColour, + m_TextRectangleOutsideFillStyle; + + // for DirectSound LPDIRECTSOUNDBUFFER m_pDirectSoundSecondaryBuffer [MAX_SOUND_BUFFERS]; *************** *** 2489,2494 **** --- 2500,2511 ---- afx_msg long WindowCreateImage(LPCTSTR Name, LPCTSTR ImageId, long Row1, long Row2, long Row3, long Row4, long Row5, long Row6, long Row7, long Row8); afx_msg long WindowImageOp(LPCTSTR Name, short Action, long Left, long Top, long Right, long Bottom, long PenColour, long PenStyle, long PenWidth, long BrushColour, LPCTSTR ImageId, long EllipseWidth, long EllipseHeight); afx_msg long WindowFont(LPCTSTR Name, LPCTSTR FontId, LPCTSTR FontName, double Size, BOOL Bold, BOOL Italic, BOOL Underline, BOOL Strikeout, short Charset, short PitchAndFamily); + afx_msg long WindowBlendImage(LPCTSTR Name, LPCTSTR ImageId, long Left, long Top, long Right, long Bottom, short Mode, double Opacity, long SrcLeft, long SrcTop, long SrcRight, long SrcBottom); + afx_msg long WindowImageFromWindow(LPCTSTR Name, LPCTSTR ImageId, LPCTSTR SourceWindow); + afx_msg void Repaint(); + afx_msg long TextRectangle(long Left, long Top, long Right, long Bottom, long BorderOffset, long BorderColour, long BorderWidth, long OutsideFillColour, long OutsideFillStyle); + afx_msg long WindowGradient(LPCTSTR Name, long Left, long Top, long Right, long Bottom, long StartColour, long EndColour, short Mode); + afx_msg long WindowFilter(LPCTSTR Name, long Left, long Top, long Right, long Bottom, short Operation, double Options); afx_msg long GetNormalColour(short WhichColour); afx_msg void SetNormalColour(short WhichColour, long nNewValue); afx_msg long GetBoldColour(short WhichColour); Index: doc_construct.cpp =================================================================== RCS file: /cvs/mushclient/doc_construct.cpp,v retrieving revision 1.36 retrieving revision 1.37 diff -c -r1.36 -r1.37 *** doc_construct.cpp 17 Jul 2008 02:25:21 -0000 1.36 --- doc_construct.cpp 30 Jul 2008 22:40:58 -0000 1.37 *************** *** 50,55 **** --- 50,62 ---- m_iForegroundMode = 0; m_iBackgroundColour = NO_COLOUR; + m_TextRectangle = CRect (0, 0, 0, 0); + m_TextRectangleBorderOffset = 0; + m_TextRectangleBorderColour = 0; + m_TextRectangleBorderWidth = 0; + m_TextRectangleOutsideFillColour = 0; + m_TextRectangleOutsideFillStyle = 0; + m_iCurrentActionSource = eUnknownActionSource; m_nBytesIn = 0; m_nBytesOut = 0; Index: functionlist.cpp =================================================================== RCS file: /cvs/mushclient/functionlist.cpp,v retrieving revision 1.49 retrieving revision 1.53 diff -c -r1.49 -r1.53 *** functionlist.cpp 24 Jul 2008 01:28:44 -0000 1.49 --- functionlist.cpp 2 Aug 2008 06:35:23 -0000 1.53 *************** *** 278,284 **** "Redraw", "ReloadPlugin", "RemoveBacktracks", ! "RemoveMapReverses", "Replace", "ReplaceNotepad", "Reset", --- 278,285 ---- "Redraw", "ReloadPlugin", "RemoveBacktracks", ! "RemoveMapReverses", ! "Repaint", "Replace", "ReplaceNotepad", "Reset", *************** *** 332,337 **** --- 333,339 ---- "StripANSI", "StopSound", "Tell", + "TextRectangle", "Trace", "TraceOut", "TranslateGerman", *************** *** 345,361 **** --- 347,366 ---- "WindowAddHotspot", "WindowArc", "WindowBezier", + "WindowBlendImage", "WindowCircleOp", "WindowCreate", "WindowCreateImage", "WindowDeleteAllHotspots", "WindowDeleteHotspot", "WindowDrawImage", + "WindowFilter", "WindowFont", "WindowFontInfo", "WindowFontList", "WindowHotspotInfo", "WindowHotspotList", + "WindowImageFromWindow", "WindowImageInfo", "WindowImageList", "WindowImageOp", Index: lua_methods.cpp =================================================================== RCS file: /cvs/mushclient/lua_methods.cpp,v retrieving revision 1.108 retrieving revision 1.112 diff -c -r1.108 -r1.112 *** lua_methods.cpp 24 Jul 2008 01:28:44 -0000 1.108 --- lua_methods.cpp 2 Aug 2008 06:35:23 -0000 1.112 *************** *** 4095,4101 **** return 0; // number of result fields } // end of L_Redraw - //---------------------------------------- // world.ReloadPlugin //---------------------------------------- --- 4095,4100 ---- *************** *** 4139,4144 **** --- 4138,4151 ---- return 0; // number of result fields } // end of L_SetRemoveMapReverses + //---------------------------------------- + // world.Repaint + //---------------------------------------- + static int L_Repaint (lua_State *L) + { + doc (L)->Repaint (); + return 0; // number of result fields + } // end of L_Repaint //---------------------------------------- // world.Replace *************** *** 4806,4811 **** --- 4813,4839 ---- //---------------------------------------- + // world.TextRectangle + //---------------------------------------- + static int L_TextRectangle (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->TextRectangle ( + my_checknumber (L, 1), // Left + my_checknumber (L, 2), // Top + my_checknumber (L, 3), // Right + my_checknumber (L, 4), // Bottom + my_checknumber (L, 5), // BorderOffset + my_checknumber (L, 6), // BorderColour + my_checknumber (L, 7), // BorderWidth + my_checknumber (L, 8), // OutsideFillColour + my_checknumber (L, 9) // OutsideFillStyle + )); + return 1; // number of result fields + } // end of L_TextRectangle + + + //---------------------------------------- // world.GetTrace //---------------------------------------- static int L_GetTrace (lua_State *L) *************** *** 4997,5002 **** --- 5025,5054 ---- } // end of L_WindowBezier //---------------------------------------- + // world.WindowBlendImage + //---------------------------------------- + static int L_WindowBlendImage (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowBlendImage ( + my_checkstring (L, 1), // Name + my_checkstring (L, 2), // ImageId + my_checknumber (L, 3), // Left + my_checknumber (L, 4), // Top + my_checknumber (L, 5), // Right + my_checknumber (L, 6), // Bottom + my_checknumber (L, 7), // Mode + my_optnumber (L, 8, 1), // Opacity + my_optnumber (L, 9, 0), // SrcLeft + my_optnumber (L, 10, 0), // SrcTop + my_optnumber (L, 11, 0), // SrcRight + my_optnumber (L, 12, 0) // SrcBottom + )); + return 1; // number of result fields + } // end of L_WindowBlendImage + + + //---------------------------------------- // world.WindowCircleOp //---------------------------------------- static int L_WindowCircleOp (lua_State *L) *************** *** 5112,5117 **** --- 5164,5187 ---- } // end of L_WindowDrawImage //---------------------------------------- + // world.WindowFilter + //---------------------------------------- + static int L_WindowFilter (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowFilter ( + my_checkstring (L, 1), // Name + my_checknumber (L, 2), // Left + my_checknumber (L, 3), // Top + my_checknumber (L, 4), // Right + my_checknumber (L, 5), // Bottom + my_checknumber (L, 6), // Operation + my_checknumber (L, 7) // Options + )); + return 1; // number of result fields + } // end of L_WindowFilter + + //---------------------------------------- // world.WindowFont //---------------------------------------- static int L_WindowFont (lua_State *L) *************** *** 5159,5164 **** --- 5229,5253 ---- } // end of L_WindowFontList //---------------------------------------- + // world.WindowGradient + //---------------------------------------- + static int L_WindowGradient (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowGradient ( + my_checkstring (L, 1), // Name + my_checknumber (L, 2), // Left + my_checknumber (L, 3), // Top + my_checknumber (L, 4), // Right + my_checknumber (L, 5), // Bottom + my_checknumber (L, 6), // StartColour + my_checknumber (L, 7), // EndColour + my_checknumber (L, 8) // Mode + )); + return 1; // number of result fields + } // end of L_WindowGradient + + //---------------------------------------- // world.WindowHotspotInfo //---------------------------------------- static int L_WindowHotspotInfo (lua_State *L) *************** *** 5184,5189 **** --- 5273,5293 ---- } // end of L_WindowHotspotList //---------------------------------------- + // world.WindowImageFromWindow + //---------------------------------------- + static int L_WindowImageFromWindow (lua_State *L) + { + CMUSHclientDoc *pDoc = doc (L); + lua_pushnumber (L, pDoc->WindowImageFromWindow ( + my_checkstring (L, 1), // Name + my_checkstring (L, 2), // ImageId + my_checkstring (L, 3) // SourceWindow + )); + + return 1; + } // end of L_WindowImageFromWindow + + //---------------------------------------- // world.WindowImageInfo //---------------------------------------- static int L_WindowImageInfo (lua_State *L) *************** *** 5720,5725 **** --- 5824,5830 ---- {"RemoveBacktracks", L_RemoveBacktracks}, {"GetRemoveMapReverses", L_GetRemoveMapReverses}, {"SetRemoveMapReverses", L_SetRemoveMapReverses}, + {"Repaint", L_Repaint}, {"Replace", L_Replace}, {"ReplaceNotepad", L_ReplaceNotepad}, {"Reset", L_Reset}, *************** *** 5774,5779 **** --- 5879,5885 ---- {"StripANSI", L_StripANSI}, {"StopSound", L_StopSound}, {"Tell", L_Tell}, + {"TextRectangle", L_TextRectangle}, {"GetTrace", L_GetTrace}, {"SetTrace", L_SetTrace}, {"TraceOut", L_TraceOut}, *************** *** 5788,5804 **** --- 5894,5914 ---- {"WindowAddHotspot", L_WindowAddHotspot}, {"WindowArc", L_WindowArc}, {"WindowBezier", L_WindowBezier}, + {"WindowBlendImage", L_WindowBlendImage}, {"WindowCircleOp", L_WindowCircleOp}, {"WindowCreate", L_WindowCreate}, {"WindowCreateImage", L_WindowCreateImage}, {"WindowDeleteAllHotspots", L_WindowDeleteAllHotspots}, {"WindowDeleteHotspot", L_WindowDeleteHotspot}, {"WindowDrawImage", L_WindowDrawImage}, + {"WindowFilter", L_WindowFilter}, {"WindowFont", L_WindowFont}, {"WindowFontInfo", L_WindowFontInfo}, {"WindowFontList", L_WindowFontList}, + {"WindowGradient", L_WindowGradient}, {"WindowHotspotInfo", L_WindowHotspotInfo}, {"WindowHotspotList", L_WindowHotspotList}, + {"WindowImageFromWindow", L_WindowImageFromWindow}, {"WindowImageInfo", L_WindowImageInfo}, {"WindowImageList", L_WindowImageList}, {"WindowImageOp", L_WindowImageOp}, Index: lua_utils.cpp =================================================================== RCS file: /cvs/mushclient/lua_utils.cpp,v retrieving revision 1.25 retrieving revision 1.26 diff -c -r1.25 -r1.26 *** lua_utils.cpp 10 Jul 2008 01:24:51 -0000 1.25 --- lua_utils.cpp 30 Jul 2008 22:40:58 -0000 1.26 *************** *** 773,778 **** --- 773,825 ---- } // end of metaphone + static int fontpicker (lua_State *L) + { + const char * fontname = luaL_optstring (L, 1, ""); // preferred name + const int fontsize = luaL_optnumber (L, 2, 10); // preferred size + const int fontcolour = luaL_optnumber (L, 3, 0); // preferred colour + + + CDC dc; + + dc.CreateCompatibleDC (NULL); + + LOGFONT lf; + + ZeroMemory (&lf, sizeof lf); + + lf.lfHeight = -MulDiv(fontsize, dc.GetDeviceCaps(LOGPIXELSY), 72); + strncpy (lf.lfFaceName, fontname, sizeof (lf.lfFaceName) - 1); + lf.lfFaceName [sizeof (lf.lfFaceName) - 1] = 0; + + lf.lfWeight = FW_NORMAL; + + CFontDialog dlg (&lf, + CF_SCREENFONTS | CF_EFFECTS | CF_FORCEFONTEXIST, + NULL, + &Frame); + + if (dlg.DoModal () != IDOK) + { + lua_pushnil (L); + return 1; + } + + lua_newtable(L); // table to hold this stuff + + MakeTableItem (L, "name", dlg.GetFaceName ()); + MakeTableItem (L, "style", dlg.GetStyleName ()); + MakeTableItem (L, "size", dlg.GetSize () / 10); + MakeTableItem (L, "colour", dlg.GetColor ()); + MakeTableItem (L, "bold", dlg.IsBold ()); + MakeTableItem (L, "italic", dlg.IsItalic ()); + MakeTableItem (L, "underline", dlg.IsUnderline ()); + MakeTableItem (L, "strikeout", dlg.IsStrikeOut ()); + MakeTableItem (L, "charset", lf.lfCharSet); + + return 1; // one table + } // end of fontpicker + int edit_distance (lua_State *L) { lua_pushinteger (L, EditDistance (luaL_checkstring (L, 1), luaL_checkstring (L, 2))); *************** *** 1325,1330 **** --- 1372,1378 ---- {"functionlist", functionlist}, {"filepicker", filepicker}, {"directorypicker", directorypicker}, + {"fontpicker", fontpicker}, {"metaphone", metaphone}, {"info", info}, {"spellcheckdialog", spellcheckdialog}, Index: methods.cpp =================================================================== RCS file: /cvs/mushclient/methods.cpp,v retrieving revision 1.242 retrieving revision 1.248 diff -c -r1.242 -r1.248 *** methods.cpp 26 Jul 2008 06:13:19 -0000 1.242 --- methods.cpp 5 Aug 2008 06:25:12 -0000 1.248 *************** *** 4242,4247 **** --- 4242,4256 ---- { 269, "Foreground image mode" }, { 270, "Background image mode" }, { 271, "Background colour" }, + { 272, "Text rectangle - left" }, + { 273, "Text rectangle - top" }, + { 274, "Text rectangle - right" }, + { 275, "Text rectangle - bottom" }, + { 276, "Text rectangle - border offset" }, + { 277, "Text rectangle - border width" }, + { 278, "Text rectangle - outside colour" }, + { 279, "Text rectangle - outside style" }, + *************** *** 4797,4802 **** --- 4806,4820 ---- case 270: SetUpVariantLong (vaResult, m_iBackgroundMode); break; case 271: SetUpVariantLong (vaResult, m_iBackgroundColour); break; + case 272: SetUpVariantLong (vaResult, m_TextRectangle.left); break; + case 273: SetUpVariantLong (vaResult, m_TextRectangle.top); break; + case 274: SetUpVariantLong (vaResult, m_TextRectangle.right); break; + case 275: SetUpVariantLong (vaResult, m_TextRectangle.bottom); break; + case 276: SetUpVariantLong (vaResult, m_TextRectangleBorderOffset); break; + case 277: SetUpVariantLong (vaResult, m_TextRectangleBorderWidth); break; + case 278: SetUpVariantLong (vaResult, m_TextRectangleOutsideFillColour); break; + case 279: SetUpVariantLong (vaResult, m_TextRectangleOutsideFillStyle); break; + case 301: if (m_tConnectTime.GetTime ()) // only if non-zero, otherwise return empty SetUpVariantDate (vaResult, COleDateTime (m_tConnectTime.GetTime ())); *************** *** 13020,13026 **** PenColour, PenStyle, PenWidth, BrushColour, ImageId, EllipseWidth, EllipseHeight); ! } long CMUSHclientDoc::WindowCreateImage(LPCTSTR Name, LPCTSTR ImageId, long Row1, long Row2, long Row3, long Row4, long Row5, long Row6, long Row7, long Row8) --- 13038,13044 ---- PenColour, PenStyle, PenWidth, BrushColour, ImageId, EllipseWidth, EllipseHeight); ! } // end of CMUSHclientDoc::WindowImageOp long CMUSHclientDoc::WindowCreateImage(LPCTSTR Name, LPCTSTR ImageId, long Row1, long Row2, long Row3, long Row4, long Row5, long Row6, long Row7, long Row8) *************** *** 13031,13039 **** return eNoSuchWindow; return it->second->CreateImage (ImageId, Row1, Row2, Row3, Row4, Row5, Row6, Row7, Row8); ! } /* --- 13049,13164 ---- return eNoSuchWindow; return it->second->CreateImage (ImageId, Row1, Row2, Row3, Row4, Row5, Row6, Row7, Row8); ! } // end of CMUSHclientDoc::WindowCreateImage ! ! ! long CMUSHclientDoc::WindowBlendImage(LPCTSTR Name, LPCTSTR ImageId, ! long Left, long Top, long Right, long Bottom, ! short Mode, double Opacity, ! long SrcLeft, long SrcTop, long SrcRight, long SrcBottom) ! { ! MiniWindowMapIterator it = m_MiniWindows.find (Name); ! ! if (it == m_MiniWindows.end ()) ! return eNoSuchWindow; ! ! return it->second->BlendImage (ImageId, Left, Top, Right, Bottom, Mode, Opacity, SrcLeft, SrcTop, SrcRight, SrcBottom); ! } // end of CMUSHclientDoc::WindowBlendImage ! ! ! long CMUSHclientDoc::WindowImageFromWindow(LPCTSTR Name, LPCTSTR ImageId, LPCTSTR SourceWindow) ! { ! MiniWindowMapIterator it = m_MiniWindows.find (Name); ! ! if (it == m_MiniWindows.end ()) ! return eNoSuchWindow; ! ! CMiniWindow * pDestWindow = it->second; ! ! it = m_MiniWindows.find (SourceWindow); ! ! if (it == m_MiniWindows.end ()) ! return eNoSuchWindow; ! ! CMiniWindow * pSrcWindow = it->second; ! ! return pDestWindow->ImageFromWindow (ImageId, pSrcWindow); ! } // end of CMUSHclientDoc::WindowImageFromWindow + void CMUSHclientDoc::Repaint() + { + UpdateAllViews (NULL); + + for(POSITION pos = GetFirstViewPosition(); pos != NULL; ) + { + CView* pView = GetNextView(pos); + + if (pView->IsKindOf(RUNTIME_CLASS(CMUSHView))) + { + CMUSHView* pmyView = (CMUSHView*)pView; + pmyView->UpdateWindow (); + } // end of being a CMUSHView + } // end of loop through views + + } // end of CMUSHclientDoc::Repaint + + + + long CMUSHclientDoc::TextRectangle(long Left, long Top, long Right, long Bottom, + long BorderOffset, + long BorderColour, long BorderWidth, + long OutsideFillColour, long OutsideFillStyle) + { + + + CBrush br; + + if (ValidateBrushStyle (OutsideFillStyle, BorderColour, OutsideFillColour, br) != eOK) + return eBrushStyleNotValid; + + m_TextRectangle = CRect (Left, Top, Right, Bottom); + + m_TextRectangleBorderOffset = BorderOffset; + m_TextRectangleBorderColour = BorderColour; + m_TextRectangleBorderWidth = BorderWidth; + m_TextRectangleOutsideFillColour = OutsideFillColour; + m_TextRectangleOutsideFillStyle = OutsideFillStyle; + + Redraw (); + return eOK; + } // end of CMUSHclientDoc::TextRectangle + + + + long CMUSHclientDoc::WindowGradient(LPCTSTR Name, + long Left, long Top, long Right, long Bottom, + long StartColour, long EndColour, + short Mode) + { + MiniWindowMapIterator it = m_MiniWindows.find (Name); + + if (it == m_MiniWindows.end ()) + return eNoSuchWindow; + + return it->second->Gradient (Left, Top, Right, Bottom, + StartColour, EndColour, + Mode); + } // end of CMUSHclientDoc::WindowGradient + + + long CMUSHclientDoc::WindowFilter(LPCTSTR Name, long Left, long Top, long Right, long Bottom, + short Operation, double Options) + { + MiniWindowMapIterator it = m_MiniWindows.find (Name); + + if (it == m_MiniWindows.end ()) + return eNoSuchWindow; + + return it->second->Filter (Left, Top, Right, Bottom, + Operation, Options); + } // CMUSHclientDoc::WindowFilter + /* Index: miniwindow.cpp =================================================================== RCS file: /cvs/mushclient/miniwindow.cpp,v retrieving revision 1.20 retrieving revision 1.28 diff -c -r1.20 -r1.28 *** miniwindow.cpp 26 Jul 2008 06:13:19 -0000 1.20 --- miniwindow.cpp 6 Aug 2008 00:05:38 -0000 1.28 *************** *** 6,11 **** --- 6,12 ---- #include "MUSHclient.h" #include "doc.h" #include "errors.h" + #include "color.h" // constructor *************** *** 308,317 **** } ! static long ValidateBrushStyle (const long BrushStyle, ! const long PenColour, ! const long BrushColour, ! CBrush & br) { --- 309,318 ---- } ! long ValidateBrushStyle (const long BrushStyle, ! const long PenColour, ! const long BrushColour, ! CBrush & br) { *************** *** 994,999 **** --- 995,1002 ---- dc.SetBkMode (TRANSPARENT); + dc.SetStretchBltMode (HALFTONE); // looks better when squashed + BITMAP bi; bitmap->GetBitmap(&bi); *************** *** 1562,1568 **** CBitmap * pImage = new CBitmap; ! WORD wBits[8] = { Row1, Row2, Row3, Row4, Row5, Row6, Row7, Row8 }; pImage->CreateBitmap (8, 8, 1, 1, wBits); --- 1565,1572 ---- CBitmap * pImage = new CBitmap; ! // bottom row comes first in a bitmap ! WORD wBits[8] = { Row8, Row7, Row6, Row5, Row4, Row3, Row2, Row1 }; pImage->CreateBitmap (8, 8, 1, 1, wBits); *************** *** 1570,1572 **** --- 1574,2724 ---- return eOK; } // end of CMiniWindow::CreateImage + + // see: http://www.nathanm.com/photoshop-blending-math/ + // and: http://www.pegtop.net/delphi/articles/blendmodes/ + + #define uint8 unsigned char + #define sqr(x) ((x)*(x)) // square of x + + // A = blend, B = base + + #define Blend_Normal(A,B) ((uint8)(A)) + #define Blend_Lighten(A,B) ((uint8)((B > A) ? B:A)) + #define Blend_Darken(A,B) ((uint8)((B > A) ? A:B)) + #define Blend_Multiply(A,B) ((uint8)((A * B) / 255)) + #define Blend_Average(A,B) ((uint8)((A + B) / 2)) + #define Blend_Add(A,B) ((uint8)((A + B > 255) ? 255:(A + B))) + #define Blend_Subtract(A,B) ((uint8)((A + B < 255) ? 0:(A + B - 255))) + #define Blend_Difference(A,B) ((uint8)(abs(A - B))) + #define Blend_Negation(A,B) ((uint8)(255 - abs(255 - A - B))) + #define Blend_Screen(A,B) ((uint8)(255 - (((255 - A) * (255 - B)) >> 8))) + #define Blend_Exclusion(A,B) ((uint8)(A + B - 2 * A * B / 255)) + #define Blend_Overlay(A,B) ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255))) + #define Blend_SoftLight(A,B) ((uint8) ((A * B) >> 8) + ((B * (255 - (((255 - B) * (255-A)) >> 8) - ((A * B) >> 8) )) >> 8) ) // c = ((A * B) >> 8) + #define Blend_HardLight(A,B) (Blend_Overlay(B,A)) + #define Blend_ColorDodge(A,B) ((uint8)((A == 255) ? A:((B << 8 ) / (255 - A) > 255) ? 255:((B << 8 ) / (255 - A)))) + #define Blend_ColorBurn(A,B) ((uint8)((A == 0) ? 0:((255 - (((255 - B) << 8 ) / A)) < 0) ? 0:(255 - (((255 - B) << 8 ) / A)))) + #define Blend_LinearDodge(A,B) (Blend_Add(A,B)) + #define Blend_LinearBurn(A,B) (Blend_Subtract(A,B)) + #define Blend_LinearLight(A,B) ((uint8)(A < 128) ? Blend_LinearBurn((2 * A),B):Blend_LinearDodge((2 * (A - 128)),B)) + #define Blend_VividLight(A,B) ((uint8)(A < 128) ? Blend_ColorBurn((2 * A),B):Blend_ColorDodge((2 * (A - 128)),B)) + #define Blend_PinLight(A,B) ((uint8)(A < 128) ? Blend_Darken((2 * A),B):Blend_Lighten((2 *(A - 128)),B)) + #define Blend_HardMix(A,B) ((uint8)(A < 255 - B) ? 0:255) + #define Blend_Reflect(A,B) ((uint8)((B == 255) ? B:((A * A / (255 - B) > 255) ? 255:(A * A / (255 - B))))) + #define Blend_Glow(A,B) (Blend_Reflect(B,A)) + #define Blend_Phoenix(A,B) ((uint8)(min(A,B) - max(A,B) + 255)) + #define Blend_Opacity(A,B,F,O) ((uint8)(O * F(A,B) + (1 - O) * B)) + + #define Simple_Opacity(B,X,O) ((uint8)(O * X + (1 - O) * B)) + + #define Blend_InverseColorDodge(A,B) Blend_ColorDodge (B, A) + #define Blend_InverseColorBurn(A,B) Blend_ColorBurn (B, A) + #define Blend_Freeze(A,B) ((uint8)((A == 0) ? A:((255 - sqr(255 - B)/ A < 0) ? 0:(255 - sqr(255 - B) / A)))) + #define Blend_Heat(A,B) Blend_Freeze (B, A) + #define Blend_Stamp(A,B) ((uint8)((B + 2*A - 256 < 0) ? 0 : (B + 2*A - 256 > 255) ? 255 : (B + 2*A - 256) )) + #define Blend_Interpolate(A,B) ((uint8)((cos_table [A] + cos_table [B]> 255) ? 255 : (cos_table [A] + cos_table [B]) )) + + #define Blend_Xor(A,B) ((uint8) A ^ B ) + #define Blend_And(A,B) ((uint8) A & B ) + #define Blend_Or(A,B) ((uint8) A | B ) + #define Blend_A(A,B) ((uint8) (A)) + #define Blend_B(A,B) ((uint8) (B)) + + #define Blend_It(Op) \ + do \ + if (Opacity < 1.0) \ + for (i = 0; i < count; i++) \ + pB [i] = Blend_Opacity (pA [i], pB [i], Op, Opacity);\ + else\ + for (i = 0; i < count; i ++)\ + pB [i] = Op (pA [i], pB [i]);\ + while (false) + + + // we have to do this a row at a time, because there might be a filler at the end of each row + // and thus, a discontinuity which throws out the r/g/b sequence + #define Colour_Op(fR,fG,fB) \ + do \ + { \ + for (row = 0; row < iHeight; row++)\ + {\ + long base = row * perline;\ + unsigned char rA, gA, bA, rB, gB, bB; \ + if (Opacity < 1.0) \ + for (i = 0; i < perline - 2; ) \ + {\ + bA = pA [base + i]; \ + gA = pA [base + i + 1]; \ + rA = pA [base + i + 2]; \ + bB = pB [base + i]; \ + gB = pB [base + i + 1]; \ + rB = pB [base + i + 2]; \ + pB [base + i] = Simple_Opacity (bB, fB, Opacity); \ + i++;\ + pB [base + i] = Simple_Opacity (gB, fG, Opacity); \ + i++;\ + pB [base + i] = Simple_Opacity (rB, fR, Opacity); \ + i++;\ + }\ + else\ + for (i = 0; i < perline - 2;)\ + {\ + bA = pA [base + i]; \ + gA = pA [base + i + 1]; \ + rA = pA [base + i + 2]; \ + bB = pB [base + i]; \ + gB = pB [base + i + 1]; \ + rB = pB [base + i + 2]; \ + pB [base + i] = fB; \ + i++;\ + pB [base + i] = fG; \ + i++;\ + pB [base + i] = fR; \ + i++;\ + }\ + }\ + }\ + while (false) + + + int BytesPerLine (int nWidth, int nBitsPerPixel) + { + return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8; + } + + + long CMiniWindow::BlendImage(LPCTSTR ImageId, + long Left, long Top, long Right, long Bottom, + short Mode, double Opacity, + long SrcLeft, long SrcTop, long SrcRight, long SrcBottom) + { + ImageMapIterator it = m_Images.find (ImageId); + + if (it == m_Images.end ()) + return eImageNotInstalled; + + if (Opacity < 0.0 || Opacity > 1.0) + return eBadParameter; + + CBitmap * bitmap = it->second; + + BITMAP bi; + bitmap->GetBitmap(&bi); + + // calculate size of desired rectangle + long iWidth = FixRight (Right) - Left; + long iHeight = FixBottom (Bottom) - Top; + + // adjust so that -1 means 1 from right + if (SrcRight <= 0) + SrcRight = bi.bmWidth + SrcRight; + + if (SrcBottom <= 0) + SrcBottom = bi.bmHeight + SrcBottom; + + // width and heigh are the smaller of the two rectangles + iWidth = min (iWidth, SrcRight - SrcLeft); + iHeight = min (iHeight, SrcBottom - SrcTop); + + if (iWidth <= 0 || iHeight <= 0) // sanity check + return eOK; + + // upper layer (from image id) + CDC A_DC; + A_DC.CreateCompatibleDC(&dc); + CBitmap A_bmp; + + BITMAPINFO bmiA; + ZeroMemory (&bmiA, sizeof bmiA); + + bmiA.bmiHeader.biSize = sizeof bmiA; + bmiA.bmiHeader.biWidth = iWidth; + bmiA.bmiHeader.biHeight = iHeight; + bmiA.bmiHeader.biPlanes = 1; + bmiA.bmiHeader.biBitCount = 24; + bmiA.bmiHeader.biCompression = BI_RGB; + bmiA.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); + + unsigned char * pA = NULL; + + HBITMAP hbmA = CreateDIBSection(NULL, &bmiA, DIB_RGB_COLORS, (void**) &pA, NULL, 0); + + HBITMAP hOldAbmp = (HBITMAP) SelectObject(A_DC.m_hDC, hbmA); + + //copy part from image to upper layer + CDC bmDC; + bmDC.CreateCompatibleDC(&dc); + CBitmap *pOldbmp = bmDC.SelectObject(bitmap); + + A_DC.BitBlt (0, 0, iWidth, iHeight, &bmDC, SrcLeft, SrcTop, SRCCOPY); + bmDC.SelectObject(pOldbmp); + + + // base image (from miniwindow) + + CDC B_DC; + B_DC.CreateCompatibleDC(&dc); + CBitmap B_bmp; + + BITMAPINFO bmiB; + ZeroMemory (&bmiB, sizeof bmiB); + + bmiB.bmiHeader.biSize = sizeof bmiB; + bmiB.bmiHeader.biWidth = iWidth; + bmiB.bmiHeader.biHeight = iHeight; + bmiB.bmiHeader.biPlanes = 1; + bmiB.bmiHeader.biBitCount = 24; + bmiB.bmiHeader.biCompression = BI_RGB; + bmiB.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); + + unsigned char * pB = NULL; + + HBITMAP hbmB = CreateDIBSection(dc.m_hDC, &bmiB, DIB_RGB_COLORS, (void**) &pB, NULL, 0); + + HBITMAP hOldBbmp = (HBITMAP) SelectObject(B_DC.m_hDC, hbmB); + + // copy base image from miniwindow to bitmap + B_DC.BitBlt (0, 0, iWidth, iHeight, &dc, Left, Top, SRCCOPY); + + + // manipulate image here A = blend, B = base + + + long count = bmiB.bmiHeader.biSizeImage; + long perline = BytesPerLine (iWidth, 24); + + long i, row; + + switch (Mode) + { + + // normal modes + case 1: Blend_It (Blend_Normal); break; + case 2: Blend_It (Blend_Average); break; + + case 3: // Blend_Interpolate + { + // precompute cos table + unsigned char cos_table [256]; + double pi_div255 = 3.1415926535898 / 255.0; + for (i = 0; i < 256; i++) + { + double a = 64.0 - cos ((double) i * pi_div255) * 64.0; + cos_table [i] = (uint8) (a + 0.5); // round + } + Blend_It (Blend_Interpolate); + } + break; + + case 4: // dissolve - randomly choose pixels based on opacity + for (i = 0; i < count; i++) + pB [i] = (genrand () < Opacity) ? pA [i] : pB [i]; + break; + + // darkening modes + case 5: Blend_It (Blend_Darken); break; + case 6: Blend_It (Blend_Multiply); break; + case 7: Blend_It (Blend_ColorBurn); break; + case 8: Blend_It (Blend_LinearBurn); break; + case 9: Blend_It (Blend_InverseColorBurn); break; + case 10: Blend_It (Blend_Subtract); break; + + // lightening modes + case 11: Blend_It (Blend_Lighten); break; + case 12: Blend_It (Blend_Screen); break; + case 13: Blend_It (Blend_ColorDodge); break; + case 14: Blend_It (Blend_LinearDodge);break; + case 15: Blend_It (Blend_InverseColorDodge); break; + case 16: Blend_It (Blend_Add); break; + + // soft/hard light etc. + case 17: Blend_It (Blend_Overlay); break; + case 18: Blend_It (Blend_SoftLight); break; + case 19: Blend_It (Blend_HardLight); break; + case 20: Blend_It (Blend_VividLight); break; + case 21: Blend_It (Blend_LinearLight);break; + case 22: Blend_It (Blend_PinLight); break; + case 23: Blend_It (Blend_HardMix); break; + + // difference modes + case 24: Blend_It (Blend_Difference); break; + case 25: Blend_It (Blend_Exclusion); break; + + // glow modes + case 26: Blend_It (Blend_Reflect); break; + case 27: Blend_It (Blend_Glow); break; + case 28: Blend_It (Blend_Freeze); break; + case 29: Blend_It (Blend_Heat); break; + + case 30: Blend_It (Blend_Negation); break; + case 31: Blend_It (Blend_Phoenix); break; + case 32: Blend_It (Blend_Stamp); break; + + // logical modes + case 33: Blend_It (Blend_Xor); break; + case 34: Blend_It (Blend_And); break; + case 35: Blend_It (Blend_Or); break; + + // the follow modes take one colour from the blend and retain 2 from the base + case 36: Colour_Op (rA, gB, bB); break; // red + case 37: Colour_Op (rB, gA, bB); break; // green + case 38: Colour_Op (rB, gB, bA); break; // blue + + // the follow modes take two colours from the blend and retain 1 from the base + case 39: Colour_Op (rA, gA, bB); break; // yellow + case 40: Colour_Op (rB, gA, bA); break; // cyan + case 41: Colour_Op (rA, gB, bA); break; // magenta + + // limit green + case 42: Colour_Op (rA, (gA > rA) ? rA : gA, bA); break; // green limited by red + case 43: Colour_Op (rA, (gA > bA) ? bA : gA, bA); break; // green limited by blue + case 44: Colour_Op (rA, (gA > ((rA + bA) / 2)) ? ((rA + bA) / 2) : gA, bA); break; // green limited by average of red and blue + + // limit blue + case 45: Colour_Op (rA, gA, (bA > rA) ? rA : bA); break; // blue limited by red + case 46: Colour_Op (rA, gA, (bA > gA) ? gA : bA); break; // blue limited by green + case 47: Colour_Op (rA, gA, (bA > ((rA + gA) / 2)) ? ((rA + gA) / 2) : bA); break; // blue limited by average of red and green + + // limit red + case 48: Colour_Op ((rA > gA) ? gA : rA, gA, bA); break; // red limited by green + case 49: Colour_Op ((rA > bA) ? bA : rA, gA, bA); break; // red limited by blue + case 50: Colour_Op ((rA > ((gA + bA) / 2)) ? ((gA + bA) / 2) : rA, gA, bA); break; // red limited by average of green and blue + + // select single colour + case 51: Colour_Op (rA, 0, 0); break; // red only (looks red) + case 52: Colour_Op (0, gA, 0); break; // green only (looks green) + case 53: Colour_Op (0, 0, bA); break; // blue only (looks blue) + + // discard single colour + case 54: Colour_Op (0, gA, bA); break; // discard red (looks cyan) + case 55: Colour_Op (rA, 0, bA); break; // discard green (looks magenta) + case 56: Colour_Op (rA, gA, 0); break; // discard blue (looks yellow) + + // one colour to all channels (ie. it looks grey) + case 57: Colour_Op (rA, rA, rA); break; // all red + case 58: Colour_Op (gA, gA, gA); break; // all green + case 59: Colour_Op (bA, bA, bA); break; // all blue + + case 60: // Hue mode + { + for (row = 0; row < iHeight; row++) + { + long base = row * perline; + unsigned char rA, gA, bA, rB, gB, bB; + for (i = 0; i < perline - 2; ) + { + CColor cA, cB; // A = blend, B = base + bA = pA [base + i]; + gA = pA [base + i + 1]; + rA = pA [base + i + 2]; + bB = pB [base + i]; + gB = pB [base + i + 1]; + rB = pB [base + i + 2]; + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetHue (cA.GetHue ()); // hue of blend image, others from base image + pB [base + i] = Simple_Opacity (bB, cB.GetBlue (), Opacity); + i++; + pB [base + i] = Simple_Opacity (gB, cB.GetGreen (), Opacity); + i++; + pB [base + i] = Simple_Opacity (rB, cB.GetRed (), Opacity); + i++; + } + } // end for each row + } + break; + + case 61: // Saturation mode + { + for (row = 0; row < iHeight; row++) + { + long base = row * perline; + unsigned char rA, gA, bA, rB, gB, bB; + for (i = 0; i < perline - 2; ) + { + CColor cA, cB; // A = blend, B = base + bA = pA [base + i]; + gA = pA [base + i + 1]; + rA = pA [base + i + 2]; + bB = pB [base + i]; + gB = pB [base + i + 1]; + rB = pB [base + i + 2]; + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetSaturation (cA.GetSaturation ()); // saturation of blend image, others from base image + pB [base + i] = Simple_Opacity (bB, cB.GetBlue (), Opacity); + i++; + pB [base + i] = Simple_Opacity (gB, cB.GetGreen (), Opacity); + i++; + pB [base + i] = Simple_Opacity (rB, cB.GetRed (), Opacity); + i++; + } + } // end for each row + } + break; + + case 62: // Colour mode + { + for (row = 0; row < iHeight; row++) + { + long base = row * perline; + unsigned char rA, gA, bA, rB, gB, bB; + for (i = 0; i < perline - 2; ) + { + CColor cA, cB; // A = blend, B = base + bA = pA [base + i]; + gA = pA [base + i + 1]; + rA = pA [base + i + 2]; + bB = pB [base + i]; + gB = pB [base + i + 1]; + rB = pB [base + i + 2]; + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetHue (cA.GetHue ()); // hue of blend image, + cB.SetSaturation (cA.GetSaturation ()); // saturation of blend image, luminance from base image + pB [base + i] = Simple_Opacity (bB, cB.GetBlue (), Opacity); + i++; + pB [base + i] = Simple_Opacity (gB, cB.GetGreen (), Opacity); + i++; + pB [base + i] = Simple_Opacity (rB, cB.GetRed (), Opacity); + i++; + } + } // end for each row + } + break; + + /* + + Note: I don't get the same results here as using Photoshop on the same images. Not quite sure why, + some test code below seems to indicate that for all possible values of RGB, they map to HSL and back + again without error. + + In the absence of any obvious bug, I am assuming that by plugging the Luminance from one colour into the + L channel of another, I am creating an out-of-gamut colour, which then cannot be represented properly. + + I can't find, so far, any code that would limit the value to be in-gamut, so for now this Luminance (and + Colour, Saturation and Hue too, probably) should be regarded as experimental. - NJG - 2/Aug/2008. + + */ + + case 63: // Luminance mode + { + for (row = 0; row < iHeight; row++) + { + long base = row * perline; + unsigned char rA, gA, bA, rB, gB, bB; + for (i = 0; i < perline - 2; ) + { + CColor cA, cB; // A = blend, B = base + bA = pA [base + i]; + gA = pA [base + i + 1]; + rA = pA [base + i + 2]; + bB = pB [base + i]; + gB = pB [base + i + 1]; + rB = pB [base + i + 2]; + + // bit of a fudge here, but what can you do? + + // this is going to brighten the really dark pixels, however at least then they + // should retain their base colour, rather than be promoted up to something garish + + // if (rB < 12) rB = 12; + // if (gB < 12) gB = 12; + // if (bB < 12) bB = 12; + + cA.SetRGB (rA, gA, bA); + cB.SetRGB (rB, gB, bB); + + cB.SetLuminance (cA.GetLuminance ()); // luminance from blend image, others from base image + + pB [base + i] = Simple_Opacity (bB, cB.GetBlue (), Opacity); + i++; + pB [base + i] = Simple_Opacity (gB, cB.GetGreen (), Opacity); + i++; + pB [base + i] = Simple_Opacity (rB, cB.GetRed (), Opacity); + i++; + + } + } // end for each row + } + break; + + case 64: // HSL (hue to red, saturation to green, luminance to blue) + { + for (row = 0; row < iHeight; row++) + { + long base = row * perline; + unsigned char rA, gA, bA, rB, gB, bB; + for (i = 0; i < perline - 2; ) + { + CColor cA, cB; // A = blend, B = base + bA = pA [base + i]; + gA = pA [base + i + 1]; + rA = pA [base + i + 2]; + bB = pB [base + i]; + gB = pB [base + i + 1]; + rB = pB [base + i + 2]; + + cA.SetRGB (rA, gA, bA); + + pB [base + i] = Simple_Opacity (bB, cA.GetLuminance () * 255, Opacity); + i++; + pB [base + i] = Simple_Opacity (gB, cA.GetSaturation () * 255, Opacity); + i++; + pB [base + i] = Simple_Opacity (rB, (cA.GetHue () / 360.0) * 255, Opacity); + i++; + + } + } // end for each row + } + break; + + /* + case 65: // testing conversion to/from RGB to HSL and back again is consistent. + { + int r, g, b; + CColor cA; + + for (r = 0; r < 256; r ++) + for (g = 0; g < 256; g ++) + for (b = 0; b < 256; b ++) + { + cA.SetRGB (r, g, b); + cA.GetLuminance (); // force change to HSL + ASSERT (r == cA.GetRed ()); + ASSERT (g == cA.GetGreen ()); + ASSERT (b == cA.GetBlue ()); + + } + + + } + break; + + */ + + default: return eUnknownOption; + } + + // copy result back + + dc.BitBlt (Left, Top, iWidth, iHeight, &B_DC, 0, 0, SRCCOPY); + + + SelectObject(A_DC.m_hDC, hOldAbmp); + SelectObject(B_DC.m_hDC, hOldBbmp); + + DeleteObject (hbmA); + DeleteObject (hbmB); + + return eOK; + + + + } // end of CMiniWindow::BlendImage + + + // copies one miniwindow image as a stand-alone image + long CMiniWindow::ImageFromWindow(LPCTSTR ImageId, CMiniWindow * pSrcWindow) + { + + + ImageMapIterator it = m_Images.find (ImageId); + + if (it != m_Images.end ()) + { + delete it->second; // delete existing image + m_Images.erase (it); + } + + // make new bitmap of appropriate size to hold image from other miniwindow + CBitmap * pImage = new CBitmap; + pImage->CreateCompatibleBitmap (&dc, pSrcWindow->m_iWidth, pSrcWindow->m_iHeight); + + // prepare to copy it + CDC bmDC; + bmDC.CreateCompatibleDC(&dc); + CBitmap *pOldbmp = bmDC.SelectObject(pImage); + + // copy into our bitmap + bmDC.BitBlt (0, 0, pSrcWindow->m_iWidth, pSrcWindow->m_iHeight, &pSrcWindow->dc, 0, 0, SRCCOPY); + + // done + bmDC.SelectObject(pOldbmp); + + // save in map + m_Images [ImageId] = pImage; + return eOK; + + } // end of CMiniWindow::ImageFromWindow + + + long CMiniWindow::Gradient(long Left, long Top, long Right, long Bottom, + long StartColour, long EndColour, + short Mode) + { + // calculate size of desired rectangle + long iWidth = FixRight (Right) - Left; + long iHeight = FixBottom (Bottom) - Top; + + if (iWidth <= 0 || iHeight <= 0) // sanity check + return eOK; + + // upper layer (from image id) + CDC gDC; + gDC.CreateCompatibleDC(&dc); + CBitmap gbmp; + + BITMAPINFO bmi; + ZeroMemory (&bmi, sizeof bmi); + + bmi.bmiHeader.biSize = sizeof bmi; + bmi.bmiHeader.biWidth = iWidth; + bmi.bmiHeader.biHeight = iHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); + + unsigned char * pA = NULL; + + HBITMAP hbmG = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**) &pA, NULL, 0); + + HBITMAP hOldAbmp = (HBITMAP) SelectObject(gDC.m_hDC, hbmG); + + long row, col; + + double rdiff = GetRValue (EndColour) - GetRValue (StartColour), + gdiff = GetGValue (EndColour) - GetGValue (StartColour), + bdiff = GetBValue (EndColour) - GetBValue (StartColour); + double rinc = 0, ginc = 0, binc = 0; + + uint8 r = 0, g = 0, b = 0; + + switch (Mode) + { + case 1 : // horizontal (left to right) + { + double rval = GetRValue (StartColour), + gval = GetGValue (StartColour), + bval = GetBValue (StartColour); + rinc = rdiff / (double) (iWidth - 1); + ginc = gdiff / (double) (iWidth - 1); + binc = bdiff / (double) (iWidth - 1); + + // main loop is columns + for (col = 0; col < iWidth; col++) + { + r = (uint8) rval; + g = (uint8) gval; + b = (uint8) bval; + unsigned char * p = pA + col * 3; + for (row = 0; row < iHeight; row++) + { + p [0] = b; + p [1] = g; + p [2] = r; + p += BytesPerLine (iWidth, 24); + } // end of each row + rval += rinc; + gval += ginc; + bval += binc; + } // end of each column + } + break; // end of horizontal + + + case 2 : // vertical (top to bottom) + { + double rval = GetRValue (EndColour), + gval = GetGValue (EndColour), + bval = GetBValue (EndColour); + rinc = - rdiff / (double) (iHeight - 1); + ginc = - gdiff / (double) (iHeight - 1); + binc = - bdiff / (double) (iHeight - 1); + + // main loop is rows + for (row = 0; row < iHeight; row++) + { + r = (uint8) rval; + g = (uint8) gval; + b = (uint8) bval; + unsigned char * p = pA + BytesPerLine (iWidth, 24) * row; + for (col = 0; col < iWidth; col++) + { + p [0] = b; + p [1] = g; + p [2] = r; + p += 3; + } // end of each column + rval += rinc; + gval += ginc; + bval += binc; + } // end of each row + } + break; // end of vertical + + + default: return eUnknownOption; + + } // end of switch + + + // copy result back + + dc.BitBlt (Left, Top, iWidth, iHeight, &gDC, 0, 0, SRCCOPY); + + + SelectObject(gDC.m_hDC, hOldAbmp); + + DeleteObject (hbmG); + + return eOK; + + } // end of CMiniWindow::Gradient + + static void GeneralFilter (unsigned char * inbuf, long iWidth, long iHeight, + const long iPerLine, + const double Options, + const double * iMatrix, + const double iDivisor) + { + + unsigned char * pi; + long total; + + long row, col, rgb; + int i; + int iLastByte = iWidth * 3; + long window [5]; + + if (Options != 2) // 2 = vertical only + { + // horizontal + // main loop is rows + for (row = 0; row < iHeight; row++) + { + + pi = inbuf + iPerLine * row; + + + for (rgb = 0; rgb < 3; rgb++) + { + + // preload 4 slots in window for edge case (-2 to +1) + for (col = 0; col < 4; col++) + window [col + 1] = pi [min (max (rgb + (col * 3) - 6, 0), iLastByte - 1)]; + + for (col = 0; col < iLastByte - 4; col += 3) + { + // we add 3 to get to the next pixel in that colour (R, G or B) + + // insert right-most byte into window + + window [0] = window [1]; + window [1] = window [2]; + window [2] = window [3]; + window [3] = window [4]; + window [4] = pi [min (max (col + rgb + 6, 0), iLastByte - 1)]; + + total = 0; + + for (i = 0; i < 5; i++) + total += window [i] * iMatrix [i]; + + pi [col + rgb] = (uint8) (min (max (total / iDivisor, 0), 255)); + } // end of each column + } // end of each colour + + } // end of each row + } // horizontal wanted + + if (Options != 1) // 1 = horizontal only + { + + // vertical + // main loop is columns + for (col = 0; col < iLastByte; col++) + { + + // preload 4 slots in window for edge case (-2 to +1) + for (row = 0; row < 4; row++) + { + long from = min (max (row - 2, 0), iHeight - 1); + pi = inbuf + col + (from * iPerLine); + window [row + 1] = *pi; + } + + for (row = 0; row < iHeight; row++) + { + + long from = min (max (row + 3, 0), iHeight - 1); + pi = inbuf + col + (from * iPerLine); + + // insert right-most byte into window + + window [0] = window [1]; + window [1] = window [2]; + window [2] = window [3]; + window [3] = window [4]; + window [4] = *pi; + + total = 0; + + for (i = 0; i < 5; i++) + total += window [i] * iMatrix [i]; + + pi = inbuf + col + (row * iPerLine); + pi [0] = (uint8) (min (max (total / iDivisor, 0), 255)); + + } // end of each row + } // end of each column + } // vertical wanted + + } // end of Blur + + + #define CLAMP(x) (((x) < 0) ? 0 : (c > 255) ? 255 : (x)) + + static void Noise (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) + { + + unsigned char * pi = inbuf; + long count = iPerLine * iHeight; + long i, c; + double threshold = Options / 100.0; + for (i = 0; i < count; i++) + { + c = *pi; + c += (128 - genrand () * 256) * threshold; + *pi++ = CLAMP (c); + } + + } // end of Noise + + static void MonoNoise (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) + { + + unsigned char * pi = inbuf; + long count = iPerLine * iHeight / 3; + long i, j, c, row; + double threshold = Options / 100.0; + + + for (row = 0; row < iHeight; row++) + { + unsigned char * pi = inbuf + (row * iPerLine); + for (i = 0; i < iWidth; i ++) + { + j = (128 - genrand () * 256) * threshold; + + c = *pi + j; + *pi++ = CLAMP (c); + c = *pi + j; + *pi++ = CLAMP (c); + c = *pi + j; + *pi++ = CLAMP (c); + } + } // end for each row + + + } // end of MonoNoise + + + static void Brightness (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) + { + + unsigned char * pi = inbuf; + long count = iPerLine * iHeight; + long i, c; + for (i = 0; i < count; i++) + { + c = *pi; + c += Options; + *pi++ = CLAMP (c); + } + + } // end of Brightness + + + static void Contrast (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) + { + + unsigned char lookup [256]; // lookup table for speed + + unsigned char * pi = inbuf; + long count = iPerLine * iHeight; + long i; + double c; + + for (i = 0; i < 256; i++) + { + c = i - 128; // center on zero + c *= Options; // multiply by contrast + c += 128; // put back + lookup [i] = CLAMP (c); + } // end of for loop + + // now convert image using lookup table + for (i = 0; i < count; i++) + *pi++ = lookup [*pi]; + + } // end of Contrast + + static void Gamma (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options) + { + + unsigned char lookup [256]; // lookup table for speed + + unsigned char * pi = inbuf; + long count = iPerLine * iHeight; + long i; + double c; + if (Options < 0.0) + Options = 0.0; + + for (i = 0; i < 256; i++) + { + c = ( (double) i) / 255.0; // normalize it + c = pow (c, Options); + c *= 255; + lookup [i] = CLAMP (c); + } // end of for loop + + // now convert image using lookup table + for (i = 0; i < count; i++) + *pi++ = lookup [*pi]; + + } // end of Gamma + + + static void ColourBrightness (unsigned char * inbuf, long iWidth, long iHeight, + long iPerLine, double Options, long iColour) + { + + long i, row, c; + + for (row = 0; row < iHeight; row++) + { + unsigned char * pi = inbuf + (row * iPerLine) + iColour; + for (i = 0; i < iWidth; i ++) + { + c = *pi; + c += Options; + *pi = CLAMP (c); + pi += 3; + } + } // end for each row + + } // end of ColourBrightness + + + static void ColourContrast (unsigned char * inbuf, long iWidth, long iHeight, + long iPerLine, double Options, long iColour) + { + + unsigned char lookup [256]; // lookup table for speed + + long i, row; + double c; + + for (i = 0; i < 256; i++) + { + c = i - 128; // center on zero + c *= Options; // multiply by contrast + c += 128; // put back + lookup [i] = CLAMP (c); + } // end of for loop + + // now convert image using lookup table + for (row = 0; row < iHeight; row++) + { + unsigned char * pi = inbuf + (row * iPerLine) + iColour; + for (i = 0; i < iWidth; i ++) + { + *pi = lookup [*pi]; + pi += 3; + } + } // end for each row + + } // end of ColourContrast + + static void ColourGamma (unsigned char * inbuf, long iWidth, long iHeight, + long iPerLine, double Options, long iColour) + { + + unsigned char lookup [256]; // lookup table for speed + + long i, row; + double c; + + if (Options < 0.0) + Options = 0.0; + + for (i = 0; i < 256; i++) + { + c = ( (double) i) / 255.0; // normalize it + c = pow (c, Options); + c *= 255; + lookup [i] = CLAMP (c); + } // end of for loop + + // now convert image using lookup table + for (row = 0; row < iHeight; row++) + { + unsigned char * pi = inbuf + (row * iPerLine) + iColour; + for (i = 0; i < iWidth; i ++) + { + *pi = lookup [*pi]; + pi += 3; + } + } // end for each row + + } // end of ColourGamma + + + // see: http://en.wikipedia.org/wiki/Grayscale + + static void MakeGreyscale (unsigned char * inbuf, long iWidth, long iHeight, long iPerLine, double Options, const bool bLinear) + { + + unsigned char * pi = inbuf; + long count = iPerLine * iHeight / 3; + long i, row; + double c; + double threshold = Options / 100.0; + + + for (row = 0; row < iHeight; row++) + { + unsigned char * pi = inbuf + (row * iPerLine); + for (i = 0; i < iWidth; i ++) + { + + if (bLinear) + { + c = pi [0] + pi [1] + pi [2]; + c /= 3; + } + else + c = pi [0] * 0.11 + // blue (perceptual) + pi [1] * 0.59 + // green + pi [2] * 0.30; // red + + *pi++ = CLAMP (c); + *pi++ = CLAMP (c); + *pi++ = CLAMP (c); + } + } // end for each row + + + } // end of MakeGreyscale + + + long CMiniWindow::Filter(long Left, long Top, long Right, long Bottom, + short Operation, double Options) + { + + // calculate size of desired rectangle + long iWidth = FixRight (Right) - Left; + long iHeight = FixBottom (Bottom) - Top; + + if (iWidth <= 3 || iHeight <= 3) // sanity check + return eOK; + + // upper layer (from image id) + CDC gDC; + gDC.CreateCompatibleDC(&dc); + CBitmap gbmp; + + BITMAPINFO bmi; + ZeroMemory (&bmi, sizeof bmi); + + bmi.bmiHeader.biSize = sizeof bmi; + bmi.bmiHeader.biWidth = iWidth; + bmi.bmiHeader.biHeight = iHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = iHeight * BytesPerLine (iWidth, 24); + + unsigned char * pA = NULL; + + HBITMAP hbmG = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**) &pA, NULL, 0); + + HBITMAP hOldAbmp = (HBITMAP) SelectObject(gDC.m_hDC, hbmG); + + // copy base image from miniwindow to bitmap + gDC.BitBlt (0, 0, iWidth, iHeight, &dc, Left, Top, SRCCOPY); + + // manipulate image here + + switch (Operation) + { + case 1: Noise (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; + case 2: MonoNoise(pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; + case 3: // blur + { + double iMatrix [5] = { 1, 1, 1, 1, 1 }; + GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 5); + } + break; + case 4: // sharpen + { + double iMatrix [5] = { -1, -1, 7, -1, -1 }; + GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 3); + } + break; + case 5: // edge detect + { + double iMatrix [5] = { 0, 2.5, -6, 2.5, 0 }; + GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 1); + } + break; + case 6: // emboss + { + double iMatrix [5] = { 1, 2, 1, -1, -2 }; + GeneralFilter (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, iMatrix, 1); + } + break; + case 7: Brightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; + case 8: Contrast (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; + case 9: Gamma (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options); break; + case 10: ColourBrightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 2); break; // red + case 11: ColourContrast (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 2); break; // red + case 12: ColourGamma (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 2); break; // red + case 13: ColourBrightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 1); break; // green + case 14: ColourContrast (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 1); break; // green + case 15: ColourGamma (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 1); break; // green + case 16: ColourBrightness (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 0); break; // blue + case 17: ColourContrast (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 0); break; // blue + case 18: ColourGamma (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, 0); break; // blue + case 19: MakeGreyscale (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, true); break; // linear + case 20: MakeGreyscale (pA, iWidth, iHeight, BytesPerLine (iWidth, 24), Options, false); break; // perceptual + + + + default: return eUnknownOption; + + } + + // copy result back + + dc.BitBlt (Left, Top, iWidth, iHeight, &gDC, 0, 0, SRCCOPY); + + + SelectObject(gDC.m_hDC, hOldAbmp); + + DeleteObject (hbmG); + + return eOK; + + } // end of CMiniWindow::Filter + Index: mushclient.cnt =================================================================== RCS file: /cvs/mushclient/mushclient.cnt,v retrieving revision 1.51 retrieving revision 1.55 diff -c -r1.51 -r1.55 *** mushclient.cnt 24 Jul 2008 01:28:45 -0000 1.51 --- mushclient.cnt 2 Aug 2008 06:35:23 -0000 1.55 *************** *** 425,430 **** --- 425,431 ---- 3 ReloadPlugin=FNC_ReloadPlugin 3 RemoveBacktracks=FNC_RemoveBacktracks 3 RemoveMapReverses=FNC_RemoveMapReverses + 3 Repaint=FNC_Repaint 3 Replace=FNC_Replace 3 ReplaceNotepad=FNC_ReplaceNotepad 3 Reset=FNC_Reset *************** *** 478,483 **** --- 479,485 ---- 3 StripANSI=FNC_StripANSI 3 StopSound=FNC_StopSound 3 Tell=FNC_Tell + 3 TextRectangle=FNC_TextRectangle 3 Trace=FNC_Trace 3 TraceOut=FNC_TraceOut 3 TranslateGerman=FNC_TranslateGerman *************** *** 491,505 **** --- 493,510 ---- 3 WindowAddHotspot=FNC_WindowAddHotspot 3 WindowArc=FNC_WindowArc 3 WindowBezier=FNC_WindowBezier + 3 WindowBlendImage=FNC_WindowBlendImage 3 WindowCircleOp=FNC_WindowCircleOp 3 WindowCreate=FNC_WindowCreate 3 WindowCreateImage=FNC_WindowCreateImage 3 WindowDeleteAllHotspots=FNC_WindowDeleteAllHotspots 3 WindowDeleteHotspot=FNC_WindowDeleteHotspot 3 WindowDrawImage=FNC_WindowDrawImage + 3 WindowFilter=FNC_WindowFilter 3 WindowFont=FNC_WindowFont 3 WindowFontInfo=FNC_WindowFontInfo 3 WindowFontList=FNC_WindowFontList + 3 WindowImageFromWindow=FNC_WindowImageFromWindow 3 WindowImageInfo=FNC_WindowImageInfo 3 WindowImageList=FNC_WindowImageList 3 WindowImageOp=FNC_WindowImageOp Index: mushclient.hlp =================================================================== RCS file: /cvs/mushclient/mushclient.hlp,v retrieving revision 1.100 retrieving revision 1.101 diff -c -r1.100 -r1.101 Binary files /tmp/cvs1ebgzU and /tmp/cvsmp4Wle differ Index: mushclient.odl =================================================================== RCS file: /cvs/mushclient/mushclient.odl,v retrieving revision 1.132 retrieving revision 1.137 diff -c -r1.132 -r1.137 *** mushclient.odl 26 Jul 2008 06:13:31 -0000 1.132 --- mushclient.odl 5 Aug 2008 06:25:12 -0000 1.137 *************** *** 70,83 **** [id(44)] long SetCommand(BSTR Message); [id(45)] BSTR GetNotes(); [id(46)] void SetNotes(BSTR Message); ! [id(358), propget] long NormalColour(short WhichColour); ! [id(358), propput] void NormalColour(short WhichColour, long nNewValue); ! [id(359), propget] long BoldColour(short WhichColour); ! [id(359), propput] void BoldColour(short WhichColour, long nNewValue); ! [id(360), propget] long CustomColourText(short WhichColour); ! [id(360), propput] void CustomColourText(short WhichColour, long nNewValue); ! [id(361), propget] long CustomColourBackground(short WhichColour); ! [id(361), propput] void CustomColourBackground(short WhichColour, long nNewValue); [id(47)] void Redraw(); [id(48)] long ResetTimer(BSTR TimerName); [id(49)] void SetOutputFont(BSTR FontName, short PointSize); --- 70,83 ---- [id(44)] long SetCommand(BSTR Message); [id(45)] BSTR GetNotes(); [id(46)] void SetNotes(BSTR Message); ! [id(364), propget] long NormalColour(short WhichColour); ! [id(364), propput] void NormalColour(short WhichColour, long nNewValue); ! [id(365), propget] long BoldColour(short WhichColour); ! [id(365), propput] void BoldColour(short WhichColour, long nNewValue); ! [id(366), propget] long CustomColourText(short WhichColour); ! [id(366), propput] void CustomColourText(short WhichColour, long nNewValue); ! [id(367), propget] long CustomColourBackground(short WhichColour); ! [id(367), propput] void CustomColourBackground(short WhichColour, long nNewValue); [id(47)] void Redraw(); [id(48)] long ResetTimer(BSTR TimerName); [id(49)] void SetOutputFont(BSTR FontName, short PointSize); *************** *** 389,394 **** --- 389,400 ---- [id(355)] long WindowCreateImage(BSTR Name, BSTR ImageId, long Row1, long Row2, long Row3, long Row4, long Row5, long Row6, long Row7, long Row8); [id(356)] long WindowImageOp(BSTR Name, short Action, long Left, long Top, long Right, long Bottom, long PenColour, long PenStyle, long PenWidth, long BrushColour, BSTR ImageId, long EllipseWidth, long EllipseHeight); [id(357)] long WindowFont(BSTR Name, BSTR FontId, BSTR FontName, double Size, BOOL Bold, BOOL Italic, BOOL Underline, BOOL Strikeout, short Charset, short PitchAndFamily); + [id(358)] long WindowBlendImage(BSTR Name, BSTR ImageId, long Left, long Top, long Right, long Bottom, short Mode, double Opacity, long SrcLeft, long SrcTop, long SrcRight, long SrcBottom); + [id(359)] long WindowImageFromWindow(BSTR Name, BSTR ImageId, BSTR SourceWindow); + [id(360)] void Repaint(); + [id(361)] long TextRectangle(long Left, long Top, long Right, long Bottom, long BorderOffset, long BorderColour, long BorderWidth, long OutsideFillColour, long OutsideFillStyle); + [id(362)] long WindowGradient(BSTR Name, long Left, long Top, long Right, long Bottom, long StartColour, long EndColour, short Mode); + [id(363)] long WindowFilter(BSTR Name, long Left, long Top, long Right, long Bottom, short Operation, double Options); //}}AFX_ODL_METHOD }; Index: mushview.cpp =================================================================== RCS file: /cvs/mushclient/mushview.cpp,v retrieving revision 1.109 retrieving revision 1.113 diff -c -r1.109 -r1.113 *** mushview.cpp 25 Jul 2008 01:24:52 -0000 1.109 --- mushview.cpp 5 Aug 2008 06:25:12 -0000 1.113 *************** *** 485,490 **** --- 485,492 ---- OffsetRect (&r, -m_scroll_position.x, -m_scroll_position.y); + OffsetRect (&r, pDoc->m_TextRectangle.left, pDoc->m_TextRectangle.top); + if (bBackground) { COLORREF b; *************** *** 501,508 **** if (pDoc->m_bUTF_8) // Unicode output ExtTextOutW( // W = wide pDC->m_hDC, ! pDoc->m_iPixelOffset + pixel - m_scroll_position.x, ! - pDoc->m_iPixelOffset + line * pDoc->m_FontHeight - m_scroll_position.y, 0, // transparent &r, sUnicodeText, --- 503,510 ---- if (pDoc->m_bUTF_8) // Unicode output ExtTextOutW( // W = wide pDC->m_hDC, ! r.left, // pDoc->m_iPixelOffset + pixel - m_scroll_position.x, ! r.top, // - pDoc->m_iPixelOffset + line * pDoc->m_FontHeight - m_scroll_position.y, 0, // transparent &r, sUnicodeText, *************** *** 510,517 **** NULL); else // Ascii output pDC->ExtTextOut ( ! pDoc->m_iPixelOffset + pixel - m_scroll_position.x, ! - pDoc->m_iPixelOffset + line * pDoc->m_FontHeight - m_scroll_position.y, 0, // transparent &r, &pLine->text [thiscol], --- 512,519 ---- NULL); else // Ascii output pDC->ExtTextOut ( ! r.left, // pDoc->m_iPixelOffset + pixel - m_scroll_position.x, ! r.top, //- pDoc->m_iPixelOffset + line * pDoc->m_FontHeight - m_scroll_position.y, 0, // transparent &r, &pLine->text [thiscol], *************** *** 833,838 **** --- 835,841 ---- // this stuff stops the flicker when redawing stuff that is almost identical to last time CRect rcBounds; GetClientRect(&rcBounds); + CMyMemDC pDC(dc, rcBounds); int startline, *************** *** 850,855 **** --- 853,861 ---- if (!pDoc->m_FontHeight) return; + + pDC->SelectClipRgn (NULL); + CBrush backbr; CRect rect; *************** *** 866,877 **** GetClientRect (&r); pDC->SetBkMode (OPAQUE); ! pDC->FillRect (&r, &backbr); // background image if ((HBITMAP) pDoc->m_BackgroundBitmap) DrawImage (pDC, pDoc->m_BackgroundBitmap, pDoc->m_iBackgroundMode); Calculate_MiniWindow_Rectangles (pDoc, true); --- 872,954 ---- GetClientRect (&r); pDC->SetBkMode (OPAQUE); ! ! CRect TextRectangle = GetTextRectangle (); ! ! // do external fill ! if (HaveTextRectangle () && pDoc->m_TextRectangleOutsideFillStyle != BS_NULL) ! { ! CBrush br; ! ! ValidateBrushStyle (pDoc->m_TextRectangleOutsideFillStyle, ! pDoc->m_TextRectangleBorderColour, ! pDoc->m_TextRectangleOutsideFillColour, ! br); ! CPen pen; ! pen.CreatePen(PS_NULL, (int) 1, pDoc->m_TextRectangleBorderColour); ! CPen* oldPen = pDC->SelectObject(&pen); ! CBrush* oldBrush = pDC->SelectObject(&br); ! ! if (pDoc->m_TextRectangleOutsideFillStyle > 1 && pDoc->m_TextRectangleOutsideFillStyle <= 7) ! pDC->SetBkColor (pDoc->m_TextRectangleOutsideFillColour); // for hatched brushes this is the background colour ! else ! if (pDoc->m_TextRectangleOutsideFillStyle > 7) // pattern brushes ! { ! pDC->SetTextColor (pDoc->m_TextRectangleOutsideFillColour); // for hatched brushes and patterned brushes ! pDC->SetBkColor (pDoc->m_TextRectangleBorderColour); // for patterned brushes ! } ! ! pDC->Rectangle (&r); ! ! pDC->SelectObject (oldPen); ! pDC->SelectObject (oldBrush); ! ! CRect fillrect (GetTextRectangle ()); ! fillrect.InflateRect (pDoc->m_TextRectangleBorderOffset, pDoc->m_TextRectangleBorderOffset); ! fillrect.InflateRect (pDoc->m_TextRectangleBorderWidth, pDoc->m_TextRectangleBorderWidth); ! pDC->FillRect (&fillrect, &backbr); ! ! } ! else ! pDC->FillRect (&r, &backbr); // background image if ((HBITMAP) pDoc->m_BackgroundBitmap) DrawImage (pDC, pDoc->m_BackgroundBitmap, pDoc->m_iBackgroundMode); + if (HaveTextRectangle ()) + { + + if (pDoc->m_TextRectangleBorderWidth > 0) + { + // create pen + CPen pen; + pen.CreatePen (PS_SOLID, pDoc->m_TextRectangleBorderWidth, pDoc->m_TextRectangleBorderColour); + + CBrush br; + + LOGBRUSH lb; + lb.lbStyle = BS_NULL; + br.CreateBrushIndirect (&lb); + + // select into DC + CPen* oldPen = pDC->SelectObject(&pen); + CBrush* oldBrush = pDC->SelectObject(&br); + CRect r (TextRectangle); + r.InflateRect (pDoc->m_TextRectangleBorderWidth, pDoc->m_TextRectangleBorderWidth); + r.InflateRect (pDoc->m_TextRectangleBorderOffset, pDoc->m_TextRectangleBorderOffset); + pDC->Rectangle (r); + pDC->SelectObject (oldPen); + pDC->SelectObject (oldBrush); + } + + + // clip to rectangle + CRgn rgn; + rgn.CreateRectRgn (TextRectangle.left, TextRectangle.top, TextRectangle.right, TextRectangle.bottom); + pDC->SelectClipRgn (&rgn); + } // end of text rectangle + Calculate_MiniWindow_Rectangles (pDoc, true); *************** *** 909,915 **** startline = (pt.y - pDoc->m_iPixelOffset) / pDoc->m_FontHeight; ! endline = ((pt.y + r.bottom) / pDoc->m_FontHeight) + 2; if (startline < 0) startline = 0; --- 986,992 ---- startline = (pt.y - pDoc->m_iPixelOffset) / pDoc->m_FontHeight; ! endline = ((pt.y + GetOutputWindowHeight ()) / pDoc->m_FontHeight) + 2; if (startline < 0) startline = 0; *************** *** 1145,1150 **** --- 1222,1228 ---- - pDoc->m_iPixelOffset + line * pDoc->m_FontHeight + iHalfFontHeight + 1); OffsetRect (&r, -m_scroll_position.x, -m_scroll_position.y); + OffsetRect (&r, pDoc->m_TextRectangle.left, pDoc->m_TextRectangle.top); pDC->FillSolidRect (&r, pDoc->TranslateColour (RGB (132, 132, 132))); OffsetRect (&r, 0, 1); *************** *** 1164,1169 **** --- 1242,1249 ---- } + pDC->SelectClipRgn (NULL); + // foreground image if ((HBITMAP) pDoc->m_ForegroundBitmap) *************** *** 1274,1328 **** ///////////////////////////////////////////////////////////////////////////// // CMUSHView message handlers - void CMUSHView::InvalidateLines (const int iLines) - { - CMUSHclientDoc* pDoc = GetDocument(); - ASSERT_VALID(pDoc); - RECT r; - CPoint pt; - int lastline; - long right; - - - GetClientRect (&r); - right = r.right; - - lastline = pDoc->GetLastLine (); - - pt.y = (lastline * pDoc->m_FontHeight) - r.bottom; - pt.x = 0; - - if (pt.y < 0) - pt.y = 0; - - SetRect (&r, - 0, - - pDoc->m_iPixelOffset + ((m_last_line_drawn - iLines) * pDoc->m_FontHeight) - - pt.y, - pDoc->m_iPixelOffset + right, - ((m_last_line_drawn + 1) * pDoc->m_FontHeight) - - pt.y); - - - InvalidateRect (&r); - - #if REDRAW_DEBUG - ShowInvalidatedRect (this, r, RGB (255, 0, 0)); - #endif - - } // end of CMUSHView::InvalidateLines - - void CMUSHView::OnTestEnd() { CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); - RECT r; int lastline; - long right; - - GetClientRect (&r); - right = r.right; CPoint pt; --- 1354,1364 ---- *************** *** 1330,1336 **** lastline = pDoc->GetLastLine (); ! pt.y = (lastline * pDoc->m_FontHeight) - r.bottom; pt.x = 0; if (pt.y < 0) --- 1366,1373 ---- lastline = pDoc->GetLastLine (); ! pt.y = (lastline * pDoc->m_FontHeight) - GetOutputWindowHeight (); ! pt.x = 0; if (pt.y < 0) *************** *** 1339,1360 **** ScrollToPosition (pt, App.m_bSmoothScrolling); ! InvalidateLines (1); m_last_line_drawn = lastline; - // scrolling to the end of the buffer will cancel any selection - // (so we can bookmark the last line easily) - - CRgn oldrgn; - get_selection (oldrgn); - InvalidateRgn (&oldrgn); - #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); #endif - oldrgn.DeleteObject (); m_selstart_line = 0; m_selstart_col = 0; m_selend_line = 0; --- 1376,1389 ---- ScrollToPosition (pt, App.m_bSmoothScrolling); ! Invalidate (); m_last_line_drawn = lastline; #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); #endif m_selstart_line = 0; m_selstart_col = 0; m_selend_line = 0; *************** *** 1367,1387 **** { CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); - RECT r; CPoint pt = GetScrollPosition (); int lastline; - GetClientRect (&r); ! pt.y += r.bottom - pDoc->m_FontHeight; // include partial last line if necessary lastline = pDoc->GetLastLine (); ! if (pt.y > ((lastline * pDoc->m_FontHeight) - r.bottom)) ! pt.y = (lastline * pDoc->m_FontHeight) - r.bottom; ScrollToPosition (pt, false); --- 1396,1414 ---- { CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CPoint pt = GetScrollPosition (); int lastline; ! pt.y += GetOutputWindowHeight () - pDoc->m_FontHeight; // include partial last line if necessary lastline = pDoc->GetLastLine (); ! if (pt.y > ((lastline * pDoc->m_FontHeight) - GetOutputWindowHeight ())) ! pt.y = (lastline * pDoc->m_FontHeight) - GetOutputWindowHeight (); ScrollToPosition (pt, false); *************** *** 1392,1404 **** CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); - RECT r; - CPoint pt = GetScrollPosition (); ! GetClientRect (&r); ! ! pt.y -= r.bottom - pDoc->m_FontHeight; if (pt.y < 0) pt.y = 0; --- 1419,1427 ---- CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); CPoint pt = GetScrollPosition (); ! pt.y -= GetOutputWindowHeight () - pDoc->m_FontHeight; if (pt.y < 0) pt.y = 0; *************** *** 1489,1497 **** // find page size - RECT r; - - GetClientRect (&r); // find last line --- 1512,1517 ---- *************** *** 1500,1506 **** lastline = pDoc->GetLastLine (); CSize sizeTotal (pDoc->m_nWrapColumn * pDoc->m_FontWidth, lastline * pDoc->m_FontHeight), ! sizePage (r.right - r.left - pDoc->m_iPixelOffset, r.bottom - r.top), sizeLine (pDoc->m_FontWidth, pDoc->m_FontHeight); SetScrollSizes (sizeTotal, sizePage, sizeLine); --- 1520,1526 ---- lastline = pDoc->GetLastLine (); CSize sizeTotal (pDoc->m_nWrapColumn * pDoc->m_FontWidth, lastline * pDoc->m_FontHeight), ! sizePage (GetOutputWindowWidth () - pDoc->m_iPixelOffset, GetOutputWindowHeight ()), sizeLine (pDoc->m_FontWidth, pDoc->m_FontHeight); SetScrollSizes (sizeTotal, sizePage, sizeLine); *************** *** 1518,1527 **** // find page size - RECT r; - - GetClientRect (&r); - // find last line int lastline; --- 1538,1543 ---- *************** *** 1529,1535 **** lastline = pDoc->GetLastLine (); CSize sizeTotal (pDoc->m_nWrapColumn * pDoc->m_FontWidth, lastline * pDoc->m_FontHeight), ! sizePage (r.right - r.left - pDoc->m_iPixelOffset, r.bottom - r.top), sizeLine (pDoc->m_FontWidth, pDoc->m_FontHeight); SetScrollSizes (sizeTotal, sizePage, sizeLine); --- 1545,1551 ---- lastline = pDoc->GetLastLine (); CSize sizeTotal (pDoc->m_nWrapColumn * pDoc->m_FontWidth, lastline * pDoc->m_FontHeight), ! sizePage (GetOutputWindowWidth () - pDoc->m_iPixelOffset, GetOutputWindowHeight ()), sizeLine (pDoc->m_FontWidth, pDoc->m_FontHeight); SetScrollSizes (sizeTotal, sizePage, sizeLine); *************** *** 1584,1596 **** } // returns true if outside range ! bool CMUSHView::calculate_line_and_column (const CPoint & point, CClientDC & dc, int & line, int & col, const bool bHalfWay) { CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); int lastline; long lastx = 0; bool bOutside = true; --- 1600,1614 ---- } // returns true if outside range ! bool CMUSHView::calculate_line_and_column (const CPoint & pt, CClientDC & dc, int & line, int & col, const bool bHalfWay) { CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); + CPoint point (pt); + int lastline; long lastx = 0; bool bOutside = true; *************** *** 1599,1604 **** --- 1617,1625 ---- dc.SelectObject(pDoc->m_font [0]); + point.y -= pDoc->m_TextRectangle.top; + point.x -= pDoc->m_TextRectangle.left; + line = (point.y + pDoc->m_iPixelOffset + m_scroll_position.y) / pDoc->m_FontHeight; // include partial last line if necessary *************** *** 1867,1872 **** --- 1888,1899 ---- if (Mouse_Down_MiniWindow (pDoc, point, 0x10)) // LH mouse, singe click return; + // check for the rectangle, now we are past the miniwindow stuff + CRect ClientRect = GetTextRectangle (true); + + if (!ClientRect.PtInRect(point)) + return; + if (GetKeyState (VK_CONTROL) < 0) // ctrl+click { AliasMenu (orig_point); *************** *** 2080,2094 **** m_selend_col = m_pin_col = m_selstart_col = col; } // end of shift key not down ! // Get new selection region ! ! get_selection (newrgn); ! ! // Combine previously selected with new selection, excluding union ! oldrgn.CombineRgn (&oldrgn, &newrgn, RGN_XOR); ! ! // Invalidate new stuff ! InvalidateRgn (&oldrgn); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); --- 2107,2113 ---- m_selend_col = m_pin_col = m_selstart_col = col; } // end of shift key not down ! Invalidate (); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); *************** *** 2156,2167 **** if (!get_selection (newrgn) && pDoc->m_bAutoFreeze) m_freeze = true; // freeze output so they can copy or print it - - // Combine previously selected with new selection, excluding union - oldrgn.CombineRgn (&oldrgn, &newrgn, RGN_XOR); - // Invalidate new stuff ! InvalidateRgn (&oldrgn); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); --- 2175,2182 ---- if (!get_selection (newrgn) && pDoc->m_bAutoFreeze) m_freeze = true; // freeze output so they can copy or print it // Invalidate new stuff ! Invalidate (); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); *************** *** 2255,2266 **** // see if the mouse is outside the visible window ! GetClientRect (&r); if (point.y > r.bottom) doLinedown (); else ! if (point.y < 0) doLineup (); CRgn oldrgn; --- 2270,2281 ---- // see if the mouse is outside the visible window ! GetTextRect (&r); if (point.y > r.bottom) doLinedown (); else ! if (point.y < r.top) doLineup (); CRgn oldrgn; *************** *** 2279,2289 **** if (!get_selection (newrgn) && pDoc->m_bAutoFreeze) m_freeze = true; // freeze output so they can copy or print it ! // Combine previously selected with new selection, excluding union ! oldrgn.CombineRgn (&oldrgn, &newrgn, RGN_XOR); ! ! // Invalidate new stuff ! InvalidateRgn (&oldrgn); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); --- 2294,2300 ---- if (!get_selection (newrgn) && pDoc->m_bAutoFreeze) m_freeze = true; // freeze output so they can copy or print it ! Invalidate (); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); *************** *** 2337,2343 **** // see if the mouse is outside the visible window ! GetClientRect (&r); if (point.y > r.bottom) { --- 2348,2354 ---- // see if the mouse is outside the visible window ! GetTextRect (&r); if (point.y > r.bottom) { *************** *** 2345,2351 **** m_last_mouse_position.y += pDoc->m_FontHeight; } else ! if (point.y < 0) { doLineup (); m_last_mouse_position.y -= pDoc->m_FontHeight; --- 2356,2362 ---- m_last_mouse_position.y += pDoc->m_FontHeight; } else ! if (point.y < r.top) { doLineup (); m_last_mouse_position.y -= pDoc->m_FontHeight; *************** *** 2368,2382 **** extend_selection (line, col); - // Get new selection region - - get_selection (newrgn); - - // Combine previously selected with new selection, excluding union - oldrgn.CombineRgn (&oldrgn, &newrgn, RGN_XOR); - // Invalidate new stuff ! InvalidateRgn (&oldrgn); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); --- 2379,2386 ---- extend_selection (line, col); // Invalidate new stuff ! Invalidate (); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); *************** *** 2404,2410 **** long right; int oldstyle = 0; ! GetClientRect (&r); right = r.right; CPoint pt = GetScrollPosition (); --- 2408,2414 ---- long right; int oldstyle = 0; ! GetTextRect (&r); right = r.right; CPoint pt = GetScrollPosition (); *************** *** 2571,2576 **** --- 2575,2589 ---- int line, col; + // another check for the rectangle, now we are past the miniwindow stuff + CRect ClientRect = GetTextRectangle (true); + + if (!ClientRect.PtInRect(point)) + { + ::SetCursor (::LoadCursor (NULL, IDC_ARROW)); + return TRUE; + } + // what line and column is that calculate_line_and_column (point, dc, line, col, false); *************** *** 2584,2590 **** POSITION foundpos; // don't show finger pointer *past* end of last word ! long pixel = calculate_width (line, pLine->len, pDoc, dc) + pDoc->m_iPixelOffset; if (pDoc->FindStyle (pLine, col, iCol, pStyle, foundpos)) { --- 2597,2603 ---- POSITION foundpos; // don't show finger pointer *past* end of last word ! long pixel = calculate_width (line, pLine->len, pDoc, dc) + pDoc->m_iPixelOffset + pDoc->m_TextRectangle.left; if (pDoc->FindStyle (pLine, col, iCol, pStyle, foundpos)) { *************** *** 2700,2711 **** { CMUSHclientDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); - - RECT r; int lastline; - GetClientRect (&r); - CPoint pt = GetScrollPosition (); pt.y += pDoc->m_FontHeight; --- 2713,2720 ---- *************** *** 2717,2724 **** //if (pt.y > (pDoc->m_iPixelOffset + (lastline * pDoc->m_FontHeight) - r.bottom)) // pt.y = pDoc->m_iPixelOffset + (lastline * pDoc->m_FontHeight) - r.bottom; ! if (pt.y > ((lastline * pDoc->m_FontHeight) - r.bottom)) ! pt.y = (lastline * pDoc->m_FontHeight) - r.bottom; ScrollToPosition (pt, App.m_bSmoothScrolling); --- 2726,2733 ---- //if (pt.y > (pDoc->m_iPixelOffset + (lastline * pDoc->m_FontHeight) - r.bottom)) // pt.y = pDoc->m_iPixelOffset + (lastline * pDoc->m_FontHeight) - r.bottom; ! if (pt.y > ((lastline * pDoc->m_FontHeight) - GetOutputWindowHeight ())) ! pt.y = (lastline * pDoc->m_FontHeight) - GetOutputWindowHeight (); ScrollToPosition (pt, App.m_bSmoothScrolling); *************** *** 2820,2828 **** // find page size - RECT r; - - GetClientRect (&r); // find last line --- 2829,2834 ---- *************** *** 2831,2837 **** lastline = pDoc->GetLastLine (); CSize sizeTotal (pDoc->m_nWrapColumn * pDoc->m_FontWidth, lastline * pDoc->m_FontHeight), ! sizePage (r.right - r.left - pDoc->m_iPixelOffset, r.bottom - r.top), sizeLine (pDoc->m_FontWidth, pDoc->m_FontHeight); SetScrollSizes (sizeTotal, sizePage, sizeLine); --- 2837,2843 ---- lastline = pDoc->GetLastLine (); CSize sizeTotal (pDoc->m_nWrapColumn * pDoc->m_FontWidth, lastline * pDoc->m_FontHeight), ! sizePage (GetOutputWindowWidth () - pDoc->m_iPixelOffset, GetOutputWindowHeight ()), sizeLine (pDoc->m_FontWidth, pDoc->m_FontHeight); SetScrollSizes (sizeTotal, sizePage, sizeLine); *************** *** 2891,2897 **** dc.GetTextMetrics(&tm); ! int iWidth = (r.right - r.left - pDoc->m_iPixelOffset) / tm.tmAveCharWidth; // ensure in range that we allow if (iWidth < 20) --- 2897,2903 ---- dc.GetTextMetrics(&tm); ! int iWidth = (GetOutputWindowWidth () - pDoc->m_iPixelOffset) / tm.tmAveCharWidth; // ensure in range that we allow if (iWidth < 20) *************** *** 3962,3967 **** --- 3968,3979 ---- if (Mouse_Tooltip_MiniWindow (pDoc, CursorPos, pNMHDR)) return TRUE; + // another check for the rectangle, now we are past the miniwindow stuff + ClientRect = GetTextRectangle (); + + if (!ClientRect.PtInRect(CursorPos)) + return FALSE; + dc.SelectObject(pDoc->m_font [0]); if (calculate_line_and_column (CursorPos, dc, line, col, false)) pTTT->szText [0] = 0; // cursor is outside a line *************** *** 3977,3983 **** int iCol = 0; // don't do it *past* end of last word ! long pixel = calculate_width (line, pLine->len, pDoc, dc) + pDoc->m_iPixelOffset; if (CursorPos.x < pixel && pDoc->FindStyle (pLine, col, iCol, pStyle, foundpos)) --- 3989,3995 ---- int iCol = 0; // don't do it *past* end of last word ! long pixel = calculate_width (line, pLine->len, pDoc, dc) + pDoc->m_iPixelOffset - pDoc->m_TextRectangle.left; if (CursorPos.x < pixel && pDoc->FindStyle (pLine, col, iCol, pStyle, foundpos)) *************** *** 4227,4233 **** RemoveToolTip (); GetClientRect (&r); // if we can do a smooth scroll, well let's do it! ! if (abs (iDeltaY) < r.bottom) { // very smooth scrolling --- 4239,4245 ---- RemoveToolTip (); GetClientRect (&r); // if we can do a smooth scroll, well let's do it! ! if (abs (iDeltaY) < GetOutputWindowHeight ()) { // very smooth scrolling *************** *** 4334,4339 **** --- 4346,4358 ---- if (Mouse_Down_MiniWindow (pDoc, point, 0x50)) // LH mouse - double click return; + + // check for the rectangle, now we are past the miniwindow stuff + CRect ClientRect = GetTextRectangle (true); + + if (!ClientRect.PtInRect(point)) + return; + dc.SelectObject(pDoc->m_font [0]); m_last_mouse_position = point; *************** *** 4427,4437 **** if (!get_selection (newrgn) && pDoc->m_bAutoFreeze) m_freeze = true; // freeze output so they can copy or print it - // Combine previously selected with new selection, excluding union - oldrgn.CombineRgn (&oldrgn, &newrgn, RGN_XOR); - // Invalidate new stuff ! InvalidateRgn (&oldrgn); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); --- 4446,4453 ---- if (!get_selection (newrgn) && pDoc->m_bAutoFreeze) m_freeze = true; // freeze output so they can copy or print it // Invalidate new stuff ! Invalidate (); #if REDRAW_DEBUG ShowInvalidatedRgn (this, oldrgn); *************** *** 4615,4621 **** GetClientRect (&r); int startline = (pt.y - pDoc->m_iPixelOffset) / pDoc->m_FontHeight + 1; ! int endline = ((pt.y + r.bottom) / pDoc->m_FontHeight) - 1; if (startline < 0) startline = 0; --- 4631,4637 ---- GetClientRect (&r); int startline = (pt.y - pDoc->m_iPixelOffset) / pDoc->m_FontHeight + 1; ! int endline = ((pt.y + GetOutputWindowHeight ()) / pDoc->m_FontHeight) - 1; if (startline < 0) startline = 0; *************** *** 4631,4637 **** { // scroll so bookmark is halfway down page CPoint pt (0, m_selstart_line * pDoc->m_FontHeight - ! (r.bottom - r.top) / 2); if (pt.y < 0) pt.y = 0; --- 4647,4653 ---- { // scroll so bookmark is halfway down page CPoint pt (0, m_selstart_line * pDoc->m_FontHeight - ! (GetOutputWindowHeight ()) / 2); if (pt.y < 0) pt.y = 0; *************** *** 4640,4646 **** // include partial last line if necessary ! lastline_pt.y = (lastline * pDoc->m_FontHeight) - r.bottom; lastline_pt.x = 0; if (lastline_pt.y < 0) --- 4656,4662 ---- // include partial last line if necessary ! lastline_pt.y = (lastline * pDoc->m_FontHeight) - GetOutputWindowHeight (); lastline_pt.x = 0; if (lastline_pt.y < 0) *************** *** 4734,4741 **** lastline = pDoc->GetLastLine (); // limit to end of screen ! if (ScrollPt.y > ((lastline * pDoc->m_FontHeight) - r.bottom)) ! ScrollPt.y = (lastline * pDoc->m_FontHeight) - r.bottom; ScrollToPosition (ScrollPt, false); --- 4750,4757 ---- lastline = pDoc->GetLastLine (); // limit to end of screen ! if (ScrollPt.y > ((lastline * pDoc->m_FontHeight) - GetOutputWindowHeight ())) ! ScrollPt.y = (lastline * pDoc->m_FontHeight) - GetOutputWindowHeight (); ScrollToPosition (ScrollPt, false); *************** *** 6483,6504 **** if (((mw->GetFlags () & MINIWINDOW_DRAW_UNDERNEATH) != 0) != bUnderneath) continue; ! // if absolute location wanted, press on ! if (mw->GetFlags () & MINIWINDOW_ABSOLUTE_LOCATION) ! continue; // if absolute location wanted, just take that and press on if (mw->GetFlags () & MINIWINDOW_ABSOLUTE_LOCATION) { ! CPoint loc = mw->GetLocation (); ! mw->m_rect.left = loc.x; ! mw->m_rect.top = loc.y; continue; } - long iWidth = mw->GetWidth (), - iHeight = mw->GetHeight (); - switch (mw->GetPosition ()) { case 0 : // stretch to output window --- 6499,6518 ---- if (((mw->GetFlags () & MINIWINDOW_DRAW_UNDERNEATH) != 0) != bUnderneath) continue; ! long iWidth = mw->GetWidth (), ! iHeight = mw->GetHeight (); // if absolute location wanted, just take that and press on if (mw->GetFlags () & MINIWINDOW_ABSOLUTE_LOCATION) { ! CPoint loc = mw->GetLocation (); ! mw->m_rect.left = loc.x; ! mw->m_rect.top = loc.y; ! mw->m_rect.right = mw->m_rect.left + iWidth; ! mw->m_rect.bottom = mw->m_rect.top + iHeight; continue; } switch (mw->GetPosition ()) { case 0 : // stretch to output window *************** *** 6681,6683 **** --- 6695,6773 ---- } // end of CMUSHView::Calculate_MiniWindow_Rectangles + + long CMUSHView::GetOutputWindowHeight () + { + + RECT r = GetTextRectangle (); + + return r.bottom - r.top; + + } // end of CMUSHView::GetOutputWindowHeight + + long CMUSHView::GetOutputWindowWidth () + { + + RECT r = GetTextRectangle (); + + return r.right - r.left; + + } // end of CMUSHView::GetOutputWindowHeight + + + // returns the rectangle we can draw text in + void CMUSHView::GetTextRect (RECT * rect) + { + *rect = GetTextRectangle (); + } // end of CMUSHView::GetTextRect + + // returns the text rectangle, if any, noramlized + RECT CMUSHView::GetTextRectangle (const bool bIncludeBorder) + { + CMUSHclientDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + CRect TextRectangle (pDoc->m_TextRectangle); + + RECT r; + + GetClientRect (&r); + + if (pDoc->m_TextRectangle != CRect (0, 0, 0, 0)) + { + // they can use -n on right/bottom to indicate offset from side + + if (TextRectangle.right <= 0) + { + TextRectangle.right += r.right; + // ensure not negative + TextRectangle.right = max (TextRectangle.right, TextRectangle.left + 20); + } + + + if (TextRectangle.bottom <= 0) + { + TextRectangle.bottom += r.bottom; + // ensure not negative + TextRectangle.bottom = max (TextRectangle.bottom, TextRectangle.top + 20); + } + + if (bIncludeBorder) + TextRectangle.InflateRect (pDoc->m_TextRectangleBorderOffset, pDoc->m_TextRectangleBorderOffset); + + return TextRectangle; + } + + return r; + + } // end of CMUSHView::GetTextRectangle + + + bool CMUSHView::HaveTextRectangle () + { + CMUSHclientDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + return pDoc->m_TextRectangle != CRect (0, 0, 0, 0); + + } // end of CMUSHView::HaveTextRectangle Index: mushview.h =================================================================== RCS file: /cvs/mushclient/mushview.h,v retrieving revision 1.36 retrieving revision 1.39 diff -c -r1.36 -r1.39 *** mushview.h 23 Jul 2008 06:24:53 -0000 1.36 --- mushview.h 5 Aug 2008 06:25:12 -0000 1.39 *************** *** 108,115 **** void Calculate_MiniWindow_Rectangles (CMUSHclientDoc* pDoc, const bool bUnderneath); void did_jump (void); - void InvalidateLines (const int iLines); void doStart (void); void doEnd (void); --- 108,120 ---- void Calculate_MiniWindow_Rectangles (CMUSHclientDoc* pDoc, const bool bUnderneath); + RECT GetTextRectangle (const bool bIncludeBorder = false); + bool HaveTextRectangle (); + long GetOutputWindowHeight () ; + long GetOutputWindowWidth () ; + void GetTextRect (RECT * rect); + void did_jump (void); void doStart (void); void doEnd (void); Index: resource.h =================================================================== RCS file: /cvs/mushclient/resource.h,v retrieving revision 1.133 retrieving revision 1.135 diff -c -r1.133 -r1.135 *** resource.h 22 Jul 2008 06:08:31 -0000 1.133 --- resource.h 2 Aug 2008 06:35:23 -0000 1.135 *************** *** 1562,1568 **** #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 ! #define _APS_NEXT_RESOURCE_VALUE 354 #define _APS_NEXT_COMMAND_VALUE 33054 #define _APS_NEXT_CONTROL_VALUE 2897 #define _APS_NEXT_SYMED_VALUE 312 --- 1562,1568 ---- #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 ! #define _APS_NEXT_RESOURCE_VALUE 356 #define _APS_NEXT_COMMAND_VALUE 33054 #define _APS_NEXT_CONTROL_VALUE 2897 #define _APS_NEXT_SYMED_VALUE 312 Index: stdafx.h =================================================================== RCS file: /cvs/mushclient/stdafx.h,v retrieving revision 1.109 retrieving revision 1.110 diff -c -r1.109 -r1.110 *** stdafx.h 16 Jul 2008 04:47:33 -0000 1.109 --- stdafx.h 30 Jul 2008 22:40:58 -0000 1.110 *************** *** 821,826 **** --- 821,831 ---- // translate a heading string (eg. for dialogs lists) #define TranslateHeading(string) TranslateGeneric (string, "headings") + // check a brush is valid, der + long ValidateBrushStyle (const long BrushStyle, + const long PenColour, + const long BrushColour, + CBrush & br); // strings marked with this macro are to be translated in the localization file // however not at runtime (ie. they are in a table, and the table lookup will be translated) Index: install/readme.txt =================================================================== RCS file: /cvs/mushclient/install/readme.txt,v retrieving revision 1.178 retrieving revision 1.180 diff -c -r1.178 -r1.180 *** install/readme.txt 26 Jul 2008 06:13:31 -0000 1.178 --- install/readme.txt 6 Aug 2008 02:35:28 -0000 1.180 *************** *** 1,7 **** ! MUSHclient version 4.34 ======================= ! Saturday, 26th July 2008 Author: Nick Gammon Web support: http://www.gammon.com.au/forum/ --- 1,7 ---- ! MUSHclient version 4.35 ======================= ! Wednesday, 6th August 2008 Author: Nick Gammon Web support: http://www.gammon.com.au/forum/