1 /* NetHack 3.6 mhmsgwnd.c $NHDT-Date: 1432512812 2015/05/25 00:13:32 $ $NHDT-Branch: master $:$NHDT-Revision: 1.32 $ */
2 /* Copyright (C) 2001 by Alex Kompel */
3 /* NetHack may be freely redistributed. See license for details. */
12 #define MSG_VISIBLE_LINES max(iflags.wc_vary_msgcount, 1)
13 #define MAX_MSG_LINES 128
14 #define MSG_LINES (int) min(iflags.msg_history, MAX_MSG_LINES)
15 #define MAXWINDOWTEXT TBUFSZ
17 #define DEFAULT_COLOR_BG_MSG COLOR_WINDOW
18 #define DEFAULT_COLOR_FG_MSG COLOR_WINDOWTEXT
20 #define MORE "--More--"
24 char text[MAXWINDOWTEXT + 1];
27 typedef struct mswin_nethack_message_window {
29 struct window_line window_text[MAX_MSG_LINES];
30 int lines_last_turn; /* lines added during the last turn */
31 int lines_not_seen; /* lines not yet seen by user after last turn or
33 int nevermore; /* We want no more --More-- prompts */
35 int xChar; /* horizontal scrolling unit */
36 int yChar; /* vertical scrolling unit */
37 int xUpper; /* average width of uppercase letters */
38 int xPos; /* current horizontal scrolling position */
39 int yPos; /* current vertical scrolling position */
40 int xMax; /* maximum horizontal scrolling position */
41 int yMax; /* maximum vertical scrolling position */
42 int xPage; /* page size of horizontal scroll bar */
43 } NHMessageWindow, *PNHMessageWindow;
44 #define LINE_PADDING_LEFT(data) (data->xChar * (2 - data->xPos))
45 #define LINE_PADDING_RIGHT(data) (0)
47 static TCHAR szMessageWindowClass[] = TEXT("MSNHMessageWndClass");
48 LRESULT CALLBACK NHMessageWndProc(HWND, UINT, WPARAM, LPARAM);
49 static void register_message_window_class(void);
50 static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
51 static void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam);
53 static void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam);
55 static COLORREF setMsgTextColor(HDC hdc, int gray);
56 static void onPaint(HWND hWnd);
57 static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
58 static BOOL can_append_text(HWND hWnd, int attr, const char *text);
59 /* check if text can be appended to the last line without wrapping */
61 static BOOL more_prompt_check(HWND hWnd);
62 /* check if "--more--" prompt needs to be displayed */
65 extern void play_sound_for_message(const char *str);
69 mswin_init_message_window()
71 static int run_once = 0;
77 register_message_window_class();
81 /* get window position */
82 if (GetNHApp()->bAutoLayout) {
83 SetRect(&rt, 0, 0, 0, 0);
85 mswin_get_window_placement(NHW_MESSAGE, &rt);
89 style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_SIZEBOX;
91 style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL | WS_SIZEBOX;
95 WS_EX_CLIENTEDGE, szMessageWindowClass, /* registered class name */
96 NULL, /* window name */
97 style, /* window style */
98 rt.left, /* horizontal position of window */
99 rt.top, /* vertical position of window */
100 rt.right - rt.left, /* window width */
101 rt.bottom - rt.top, /* window height */
102 GetNHApp()->hMainWnd, /* handle to parent or owner window */
103 NULL, /* menu handle or child identifier */
104 GetNHApp()->hApp, /* handle to application instance */
105 NULL); /* window-creation data */
108 panic("Cannot create message window");
110 /* Set window caption */
111 SetWindowText(ret, "Messages");
113 mswin_apply_window_style(ret);
119 register_message_window_class()
122 ZeroMemory(&wcex, sizeof(wcex));
124 wcex.style = CS_NOCLOSE;
125 wcex.lpfnWndProc = (WNDPROC) NHMessageWndProc;
128 wcex.hInstance = GetNHApp()->hApp;
130 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
131 wcex.hbrBackground = message_bg_brush
133 : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_MSG);
134 wcex.lpszMenuName = NULL;
135 wcex.lpszClassName = szMessageWindowClass;
137 RegisterClass(&wcex);
141 NHMessageWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
145 onCreate(hWnd, wParam, lParam);
148 case WM_MSNH_COMMAND:
149 onMSNHCommand(hWnd, wParam, lParam);
157 SetFocus(GetNHApp()->hMainWnd);
160 #ifndef MSG_WRAP_TEXT
162 onMSNH_HScroll(hWnd, wParam, lParam);
167 onMSNH_VScroll(hWnd, wParam, lParam);
171 PNHMessageWindow data;
172 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
174 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) 0);
181 PNHMessageWindow data;
184 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
186 xNewSize = LOWORD(lParam);
187 yNewSize = HIWORD(lParam);
189 if (xNewSize > 0 || yNewSize > 0) {
190 #ifndef MSG_WRAP_TEXT
191 data->xPage = xNewSize / data->xChar;
192 data->xMax = max(0, (int) (1 + data->max_text - data->xPage));
193 data->xPos = min(data->xPos, data->xMax);
195 ZeroMemory(&si, sizeof(si));
196 si.cbSize = sizeof(si);
197 si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
199 si.nMax = data->max_text;
200 si.nPage = data->xPage;
201 si.nPos = data->xPos;
202 SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
205 data->yMax = MSG_LINES - 1;
206 data->yPos = min(data->yPos, data->yMax);
208 ZeroMemory(&si, sizeof(si));
209 si.cbSize = sizeof(si);
210 si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
211 si.nMin = MSG_VISIBLE_LINES;
212 si.nMax = data->yMax + MSG_VISIBLE_LINES - 1;
213 si.nPage = MSG_VISIBLE_LINES;
214 si.nPos = data->yPos;
215 SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
218 /* update NetHack internal window position */
219 GetWindowRect(hWnd, &rt);
220 ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
221 ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
222 mswin_update_window_placement(NHW_MESSAGE, &rt);
224 /* redraw window - it does not handle incremental resizing too well */
225 InvalidateRect(hWnd, NULL, TRUE);
230 GetWindowRect(hWnd, &rt);
231 ScreenToClient(GetNHApp()->hMainWnd, (LPPOINT) &rt);
232 ScreenToClient(GetNHApp()->hMainWnd, ((LPPOINT) &rt) + 1);
233 mswin_update_window_placement(NHW_MESSAGE, &rt);
237 return DefWindowProc(hWnd, message, wParam, lParam);
243 onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
245 PNHMessageWindow data;
247 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
249 case MSNH_MSG_PUTSTR: {
250 /* Add the passed in message to the existing text. Support the
251 * adding of text that ends in newline. A newline in text
252 * will force any subsequent text that is added to be added on
255 * TODO: Text can be added with newlines occurring within the text not
256 * just at the end. As currently implemented, this can cause
257 * the text to be rendered such that the text following the
258 * newline is rendered on a new line. This can cause a poor
259 * user experience when the user has set only a single text line
260 * for the message window. In this case, the user will not see
261 * any line other then the last line of text and the --MORE--
262 * message thus missing any text that appears before the last
263 * embedded newline. This does not meet the requirements of the
265 * This code should be changed to do the right thing and split
266 * the text so that only lines that end in newlines are added to
267 * the stored window text.
269 PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr) lParam;
277 if (msg_data->append == 1) {
278 /* Forcibly append to line, even if we pass the edge */
279 strncat(data->window_text[MSG_LINES - 1].text, msg_data->text,
281 - strlen(data->window_text[MSG_LINES - 1].text));
282 } else if (msg_data->append < 0) {
283 /* remove that many chars */
284 int len = strlen(data->window_text[MSG_LINES - 1].text);
285 int newend = max(len + msg_data->append, 0);
286 data->window_text[MSG_LINES - 1].text[newend] = '\0';
288 if (can_append_text(hWnd, msg_data->attr, msg_data->text)) {
289 strncat(data->window_text[MSG_LINES - 1].text, " ",
291 - strlen(data->window_text[MSG_LINES - 1].text));
292 strncat(data->window_text[MSG_LINES - 1].text, msg_data->text,
294 - strlen(data->window_text[MSG_LINES - 1].text));
296 /* check for "--more--" */
297 if (!data->nevermore && more_prompt_check(hWnd)) {
299 char tmptext[MAXWINDOWTEXT + 1];
303 /* save original text */
304 strcpy(tmptext, data->window_text[MSG_LINES - 1].text);
306 /* text could end in newline so strip it */
307 strip_newline(data->window_text[MSG_LINES - 1].text);
309 /* append more prompt and indicate the update */
311 data->window_text[MSG_LINES - 1].text, MORE,
313 - strlen(data->window_text[MSG_LINES - 1].text));
314 InvalidateRect(hWnd, NULL, TRUE);
318 int c = mswin_nhgetch();
336 /* restore original text */
337 strcpy(data->window_text[MSG_LINES - 1].text, tmptext);
339 data->lines_not_seen = 0;
342 /* check if the string is empty */
343 for (p = data->window_text[MSG_LINES - 1].text;
344 *p && isspace((uchar) *p); p++)
348 /* last string is not empty - scroll up */
349 memmove(&data->window_text[0], &data->window_text[1],
350 (MSG_LINES - 1) * sizeof(data->window_text[0]));
353 /* append new text to the end of the array */
354 data->window_text[MSG_LINES - 1].attr = msg_data->attr;
355 strncpy(data->window_text[MSG_LINES - 1].text, msg_data->text,
358 data->lines_not_seen++;
359 data->lines_last_turn++;
363 /* reset V-scroll position to display new text */
364 data->yPos = data->yMax;
366 ZeroMemory(&si, sizeof(si));
367 si.cbSize = sizeof(si);
369 si.nPos = data->yPos;
370 SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
372 /* update window content */
373 InvalidateRect(hWnd, NULL, TRUE);
376 if (!GetNHApp()->bNoSounds)
377 play_sound_for_message(msg_data->text);
381 case MSNH_MSG_CLEAR_WINDOW: {
382 data->lines_last_turn = 0;
383 data->lines_not_seen = 0;
388 /* Create or destroy a caret */
390 CreateCaret(hWnd, NULL, 0, data->yChar);
393 /* this means we just did something interactive in this window, so
395 don't need a --More-- for the lines above.
397 data->lines_not_seen = 0;
401 case MSNH_MSG_GETTEXT: {
402 PMSNHMsgGetText msg_data = (PMSNHMsgGetText) lParam;
407 for (i = 0; i < MSG_LINES; i++)
408 if (*data->window_text[i].text) {
409 strncpy(&msg_data->buffer[buflen], data->window_text[i].text,
410 msg_data->max_size - buflen);
411 buflen += strlen(data->window_text[i].text);
412 if (buflen >= msg_data->max_size)
415 strncpy(&msg_data->buffer[buflen], "\r\n",
416 msg_data->max_size - buflen);
418 if (buflen > msg_data->max_size)
423 case MSNH_MSG_RANDOM_INPUT:
424 nhassert(0); // unexpected
427 } /* switch( wParam ) */
431 onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
433 PNHMessageWindow data;
437 UNREFERENCED_PARAMETER(lParam);
439 /* get window data */
440 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
442 ZeroMemory(&si, sizeof(si));
443 si.cbSize = sizeof(si);
444 si.fMask = SIF_PAGE | SIF_POS;
445 GetScrollInfo(hWnd, SB_VERT, &si);
447 switch (LOWORD(wParam)) {
448 // User clicked the shaft above the scroll box.
451 yInc = -(int) si.nPage;
454 // User clicked the shaft below the scroll box.
460 // User clicked the top arrow.
466 // User clicked the bottom arrow.
472 // User dragged the scroll box.
475 yInc = HIWORD(wParam) - data->yPos;
482 // If applying the vertical scrolling increment does not
483 // take the scrolling position out of the scrolling range,
484 // increment the scrolling position, adjust the position
485 // of the scroll box, and update the window. UpdateWindow
486 // sends the WM_PAINT message.
488 if (yInc = max(MSG_VISIBLE_LINES - data->yPos,
489 min(yInc, data->yMax - data->yPos))) {
491 /* ScrollWindowEx(hWnd, 0, -data->yChar * yInc,
492 (CONST RECT *) NULL, (CONST RECT *) NULL,
493 (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE);
495 InvalidateRect(hWnd, NULL, TRUE);
497 ZeroMemory(&si, sizeof(si));
498 si.cbSize = sizeof(si);
500 si.nPos = data->yPos;
501 SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
507 #ifndef MSG_WRAP_TEXT
509 onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam)
511 PNHMessageWindow data;
515 /* get window data */
516 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
518 ZeroMemory(&si, sizeof(si));
519 si.cbSize = sizeof(si);
521 GetScrollInfo(hWnd, SB_HORZ, &si);
523 switch (LOWORD(wParam)) {
524 // User clicked shaft left of the scroll box.
527 xInc = -(int) si.nPage;
530 // User clicked shaft right of the scroll box.
536 // User clicked the left arrow.
542 // User clicked the right arrow.
548 // User dragged the scroll box.
551 xInc = HIWORD(wParam) - data->xPos;
558 // If applying the horizontal scrolling increment does not
559 // take the scrolling position out of the scrolling range,
560 // increment the scrolling position, adjust the position
561 // of the scroll box, and update the window.
563 if (xInc = max(-data->xPos, min(xInc, data->xMax - data->xPos))) {
565 ScrollWindowEx(hWnd, -data->xChar * xInc, 0, (CONST RECT *) NULL,
566 (CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
567 SW_INVALIDATE | SW_ERASE);
569 ZeroMemory(&si, sizeof(si));
570 si.cbSize = sizeof(si);
572 si.nPos = data->xPos;
573 SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
577 #endif // MSG_WRAP_TEXT
580 setMsgTextColor(HDC hdc, int gray)
582 COLORREF fg, color1, color2;
584 if (message_bg_brush) {
585 color1 = message_bg_color;
586 color2 = message_fg_color;
588 color1 = (COLORREF) GetSysColor(DEFAULT_COLOR_BG_MSG);
589 color2 = (COLORREF) GetSysColor(DEFAULT_COLOR_FG_MSG);
591 /* Make a "gray" color by taking the average of the individual R,G,B
592 components of two colors. Thanks to Jonathan del Strother */
593 fg = RGB((GetRValue(color1) + GetRValue(color2)) / 2,
594 (GetGValue(color1) + GetGValue(color2)) / 2,
595 (GetBValue(color1) + GetBValue(color2)) / 2);
597 fg = message_fg_brush ? message_fg_color
598 : (COLORREF) GetSysColor(DEFAULT_COLOR_FG_MSG);
601 return SetTextColor(hdc, fg);
609 PNHMessageWindow data;
610 RECT client_rt, draw_rt;
611 int FirstLine, LastLine;
614 TCHAR wbuf[MAXWINDOWTEXT + 2];
616 COLORREF OldBg, OldFg;
618 hdc = BeginPaint(hWnd, &ps);
621 hdc, message_bg_brush ? message_bg_color
622 : (COLORREF) GetSysColor(DEFAULT_COLOR_BG_MSG));
623 OldFg = setMsgTextColor(hdc, 0);
625 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
627 GetClientRect(hWnd, &client_rt);
629 if (!IsRectEmpty(&ps.rcPaint)) {
631 0, data->yPos - (client_rt.bottom - ps.rcPaint.top) / data->yChar
636 - (client_rt.bottom - ps.rcPaint.bottom) / data->yChar);
637 y = min(ps.rcPaint.bottom, client_rt.bottom);
638 for (i = LastLine; i >= FirstLine; i--) {
639 char tmptext[MAXWINDOWTEXT + 1];
641 draw_rt.left = LINE_PADDING_LEFT(data);
642 draw_rt.right = client_rt.right - LINE_PADDING_RIGHT(data);
643 draw_rt.top = y - data->yChar;
646 cached_font * font = mswin_get_font(NHW_MESSAGE,
647 data->window_text[i].attr, hdc, FALSE);
648 oldFont = SelectObject(hdc, font->hFont);
650 /* convert to UNICODE stripping newline */
651 strcpy(tmptext, data->window_text[i].text);
652 strip_newline(tmptext);
653 NH_A2W(tmptext, wbuf, sizeof(wbuf));
654 wlen = _tcslen(wbuf);
655 setMsgTextColor(hdc, i < (MSG_LINES - data->lines_last_turn));
657 /* Find out how large the bounding rectangle of the text is */
658 DrawText(hdc, wbuf, wlen, &draw_rt,
659 DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
660 /* move that rectangle up, so that the bottom remains at the same
662 draw_rt.top = y - (draw_rt.bottom - draw_rt.top);
665 /* Now really draw it */
666 DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX | DT_WORDBREAK);
668 /* Find out the cursor (caret) position */
669 if (i == MSG_LINES - 1) {
678 /* Get the number of characters that fit on the line */
679 GetTextExtentExPoint(hdc, nbuf, nlen,
680 draw_rt.right - draw_rt.left,
681 &numfit, NULL, &size);
682 /* Search back to a space */
685 while (nnum > 0 && nbuf[nnum] != ' ')
687 /* If no space found, break wherever */
698 /* The last size is the size of the last line. Set the caret
700 This will fail automatically if we don't own the caret
702 when not in a question.)
704 SetCaretPos(draw_rt.left + size.cx,
705 draw_rt.bottom - data->yChar);
708 DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX);
709 SetCaretPos(draw_rt.left + size.cx, draw_rt.bottom - data->yChar);
711 SelectObject(hdc, oldFont);
712 y -= draw_rt.bottom - draw_rt.top;
715 SetTextColor(hdc, OldFg);
716 SetBkColor(hdc, OldBg);
721 onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
723 PNHMessageWindow data;
726 UNREFERENCED_PARAMETER(wParam);
727 UNREFERENCED_PARAMETER(lParam);
729 /* set window data */
730 data = (PNHMessageWindow) malloc(sizeof(NHMessageWindow));
732 panic("out of memory");
733 ZeroMemory(data, sizeof(NHMessageWindow));
734 data->max_text = MAXWINDOWTEXT;
735 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data);
737 /* re-calculate window size (+ font size) */
738 mswin_message_window_size(hWnd, &dummy);
742 mswin_message_window_size(HWND hWnd, LPSIZE sz)
747 PNHMessageWindow data;
750 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
754 /* -- Calculate the font size -- */
755 /* Get the handle to the client area's device context. */
757 cached_font * font = mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE);
758 saveFont = SelectObject(hdc, font->hFont);
760 /* Extract font dimensions from the text metrics. */
761 GetTextMetrics(hdc, &tm);
762 data->xChar = tm.tmAveCharWidth;
763 data->xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * data->xChar / 2;
764 data->yChar = tm.tmHeight + tm.tmExternalLeading;
767 /* Free the device context. */
768 SelectObject(hdc, saveFont);
769 ReleaseDC(hWnd, hdc);
771 /* -- calculate window size -- */
772 GetWindowRect(hWnd, &rt);
773 sz->cx = rt.right - rt.left;
774 sz->cy = rt.bottom - rt.top;
776 /* set size to accomodate MSG_VISIBLE_LINES and
777 horizontal scroll bar (difference between window rect and client rect
779 GetClientRect(hWnd, &client_rt);
780 sz->cy = sz->cy - (client_rt.bottom - client_rt.top)
781 + data->yChar * MSG_VISIBLE_LINES;
784 /* check if text can be appended to the last line without wrapping */
786 can_append_text(HWND hWnd, int attr, const char *text)
788 PNHMessageWindow data;
789 char tmptext[MAXWINDOWTEXT + 1];
795 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
797 /* cannot append if lines_not_seen is 0 (beginning of the new turn */
798 if (data->lines_not_seen == 0)
801 /* cannot append text with different attrbutes */
802 if (data->window_text[MSG_LINES - 1].attr != attr)
805 /* cannot append if current line ends in newline */
806 if (str_end_is(data->window_text[MSG_LINES - 1].text, "\n"))
809 /* check if the maximum string langth will be exceeded */
810 if (strlen(data->window_text[MSG_LINES - 1].text) + 2
811 + /* space characters */
812 strlen(text) + strlen(MORE)
816 /* check if the text is going to fit into a single line */
817 strcpy(tmptext, data->window_text[MSG_LINES - 1].text);
818 strcat(tmptext, " ");
819 strcat(tmptext, text);
820 strip_newline(tmptext);
821 strcat(tmptext, MORE);
824 cached_font * font = mswin_get_font(NHW_MESSAGE,
825 data->window_text[MSG_LINES - 1].attr, hdc, FALSE);
826 saveFont = SelectObject(hdc, font->hFont);
827 GetClientRect(hWnd, &draw_rt);
828 draw_rt.left += LINE_PADDING_LEFT(data);
829 draw_rt.right -= LINE_PADDING_RIGHT(data);
830 draw_rt.bottom = draw_rt.top; /* we only need width for the DrawText */
831 DrawText(hdc, tmptext, strlen(tmptext), &draw_rt,
832 DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
834 /* we will check against 1.5 of the font size in order to determine
835 if the text is single-line or not - just to be on the safe size */
836 retval = (draw_rt.bottom - draw_rt.top) < (data->yChar + data->yChar / 2);
838 /* free device context */
839 SelectObject(hdc, saveFont);
840 ReleaseDC(hWnd, hdc);
844 /* check if "--more--" prompt needs to be displayed
845 basically, check if the lines not seen are going to find in the message
849 more_prompt_check(HWND hWnd)
851 PNHMessageWindow data;
854 RECT client_rt, draw_rt;
856 int remaining_height;
857 char tmptext[MAXWINDOWTEXT + 1];
859 data = (PNHMessageWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA);
861 if (data->lines_not_seen == 0)
862 return FALSE; /* don't bother checking - nothig to "more" */
863 if (data->lines_not_seen >= MSG_LINES)
864 return TRUE; /* history size exceeded - always more */
866 GetClientRect(hWnd, &client_rt);
867 remaining_height = client_rt.bottom - client_rt.top;
870 cached_font * font = mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE);
871 saveFont = SelectObject(hdc, font->hFont);
872 for (i = 0; i < data->lines_not_seen; i++) {
873 /* we only need width for the DrawText */
875 client_rt.left + LINE_PADDING_LEFT(data), client_rt.top,
876 client_rt.right - LINE_PADDING_RIGHT(data), client_rt.top);
877 font = mswin_get_font(NHW_MESSAGE,
878 data->window_text[MSG_LINES - i - 1].attr, hdc, FALSE);
879 SelectObject(hdc, font->hFont);
881 strcpy(tmptext, data->window_text[MSG_LINES - i - 1].text);
882 strip_newline(tmptext);
885 strcat(tmptext, MORE);
888 DrawText(hdc, tmptext, strlen(tmptext), &draw_rt,
889 DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT);
890 if (remaining_height <= 0)
894 /* free device context */
895 SelectObject(hdc, saveFont);
896 ReleaseDC(hWnd, hdc);
897 return (remaining_height
898 <= 0); /* TRUE if lines_not_seen take more that window height */