Fix potential segfault on malloc failure
[u/mdw/putty] / sizetip.c
CommitLineData
73251d5d 1#include <windows.h>
2#include <winreg.h>
3#include <tchar.h>
4#include <stdio.h>
5
6#include "putty.h"
7
8ATOM tip_class = 0;
9
10HFONT tip_font;
11COLORREF tip_bg;
12COLORREF tip_text;
13
14LRESULT CALLBACK SizeTipWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
15{
16
17 switch (nMsg) {
b73fd1b1 18 case WM_ERASEBKGND:
73251d5d 19 return TRUE;
20
b73fd1b1 21 case WM_PAINT:
73251d5d 22 {
23 HBRUSH hbr;
24 HGDIOBJ holdbr;
25 RECT cr;
26 int wtlen;
27 LPTSTR wt;
28 HDC hdc;
29
30 PAINTSTRUCT ps;
31 hdc = BeginPaint(hWnd, &ps);
32
33 SelectObject(hdc, tip_font);
34 SelectObject(hdc, GetStockObject(BLACK_PEN));
35
36 hbr = CreateSolidBrush(tip_bg);
37 holdbr = SelectObject(hdc, hbr);
38
39 GetClientRect(hWnd, &cr);
40 Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);
41
42 wtlen = GetWindowTextLength(hWnd);
43 wt = (LPTSTR)malloc((wtlen+1)*sizeof(TCHAR));
44 GetWindowText(hWnd, wt, wtlen+1);
45
46 SetTextColor(hdc, tip_text);
47 SetBkColor(hdc, tip_bg);
48
49 TextOut(hdc, cr.left+3, cr.top+3, wt, wtlen);
50
51 free(wt);
52
53 SelectObject(hdc, holdbr);
54 DeleteObject(hbr);
55
56 EndPaint(hWnd, &ps);
57 }
58 return 0;
59
b73fd1b1 60 case WM_NCHITTEST:
73251d5d 61 return HTTRANSPARENT;
62
b73fd1b1 63 case WM_DESTROY:
73251d5d 64 DeleteObject(tip_font);
65 tip_font = NULL;
66 break;
67
b73fd1b1 68 case WM_SETTEXT:
73251d5d 69 {
70 LPCTSTR str = (LPCTSTR)lParam;
71 SIZE sz;
72 HDC hdc = CreateCompatibleDC(NULL);
73
74 SelectObject(hdc, tip_font);
75 GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
76
77 SetWindowPos(hWnd, NULL, 0, 0, sz.cx+6, sz.cy+6, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
78 InvalidateRect(hWnd, NULL, FALSE);
79
80 DeleteDC(hdc);
81 }
82 break;
83 }
84
85 return DefWindowProc(hWnd, nMsg, wParam, lParam);
86}
87
88HWND tip_wnd = NULL;
89int tip_enabled = 0;
90
91void UpdateSizeTip(HWND src, int cx, int cy)
92{
cfb1e4b1 93 TCHAR str[32];
73251d5d 94
95 if (!tip_enabled) return;
96
97 if (!tip_wnd) {
98 NONCLIENTMETRICS nci;
99
b73fd1b1 100 /* First make sure the window class is registered */
73251d5d 101
102 if (!tip_class) {
103 WNDCLASS wc;
104 wc.style = CS_HREDRAW|CS_VREDRAW;
105 wc.lpfnWndProc = SizeTipWndProc;
106 wc.cbClsExtra = 0;
107 wc.cbWndExtra = 0;
108 wc.hInstance = putty_inst;
109 wc.hIcon = NULL;
110 wc.hCursor = NULL;
111 wc.hbrBackground = NULL;
112 wc.lpszMenuName = NULL;
113 wc.lpszClassName = "SizeTipClass";
114
115 tip_class = RegisterClass(&wc);
116 }
117
b73fd1b1 118#if 0
119 /* Default values based on Windows Standard color scheme */
120
121 tip_font = GetStockObject(SYSTEM_FONT);
122 tip_bg = RGB(255, 255, 225);
123 tip_text = RGB(0, 0, 0);
124#endif
73251d5d 125
b73fd1b1 126 /* Prepare other GDI objects and drawing info */
73251d5d 127
128 tip_bg = GetSysColor(COLOR_INFOBK);
129 tip_text = GetSysColor(COLOR_INFOTEXT);
b73fd1b1 130
73251d5d 131 memset(&nci, 0, sizeof(NONCLIENTMETRICS));
132 nci.cbSize = sizeof(NONCLIENTMETRICS);
133 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nci, 0);
134 tip_font = CreateFontIndirect(&nci.lfStatusFont);
135 }
136
b73fd1b1 137 /* Generate the tip text */
73251d5d 138
cfb1e4b1 139 sprintf(str, "%dx%d", cx, cy);
73251d5d 140
141 if (!tip_wnd) {
142 HDC hdc;
143 SIZE sz;
144 RECT wr;
145 int ix, iy;
146
b73fd1b1 147 /* calculate the tip's size */
73251d5d 148
149 hdc = CreateCompatibleDC(NULL);
150 GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
151 DeleteDC(hdc);
152
153 GetWindowRect(src, &wr);
154
155 ix = wr.left;
156 if (ix<16) ix = 16;
157
158 iy = wr.top - sz.cy;
159 if (iy<16) iy = 16;
160
b73fd1b1 161 /* Create the tip window */
73251d5d 162
163 tip_wnd = CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, MAKEINTRESOURCE(tip_class), str, WS_POPUP,
b73fd1b1 164 ix, iy, sz.cx, sz.cy,
165 NULL, NULL, putty_inst, NULL);
73251d5d 166
167 ShowWindow(tip_wnd, SW_SHOWNOACTIVATE);
168
169 } else {
170
b73fd1b1 171 /* Tip already exists, just set the text */
73251d5d 172
173 SetWindowText(tip_wnd, str);
174 }
175}
176
177void EnableSizeTip(int bEnable)
178{
179 if (tip_wnd && !bEnable) {
180 DestroyWindow(tip_wnd);
181 tip_wnd = NULL;
182 }
b73fd1b1 183
73251d5d 184 tip_enabled = bEnable;
185}