1732 lines
40 KiB
C
1732 lines
40 KiB
C
// Mail and Chat Server for BPQ32 Packet Switch
|
|
//
|
|
// Console Window Module
|
|
|
|
#include "BPQChat.h"
|
|
|
|
extern BOOL WINE;
|
|
|
|
char ClassName[]="CONSOLEWINDOW";
|
|
|
|
|
|
struct UserInfo * user;
|
|
|
|
struct ConsoleInfo BBSConsole;
|
|
struct ConsoleInfo ChatConsole;
|
|
struct ConsoleInfo * ConsHeader[2] = {&BBSConsole, &ChatConsole};
|
|
|
|
struct ConsoleInfo * InitHeader;
|
|
|
|
HWND hConsole;
|
|
|
|
int AutoColours[20] = {0, 4, 9, 11, 13, 16, 17, 42, 45, 50, 61, 64, 66, 72, 81, 84, 85, 86, 87, 89};
|
|
|
|
COLORREF Colours[256] = {0,
|
|
RGB(0,0,0), RGB(0,0,128), RGB(0,0,192), RGB(0,0,255), // 1 - 4
|
|
RGB(0,64,0), RGB(0,64,128), RGB(0,64,192), RGB(0,64,255), // 5 - 8
|
|
RGB(0,128,0), RGB(0,128,128), RGB(0,128,192), RGB(0,128,255), // 9 - 12
|
|
RGB(0,192,0), RGB(0,192,128), RGB(0,192,192), RGB(0,192,255), // 13 - 16
|
|
RGB(0,255,0), RGB(0,255,128), RGB(0,255,192), RGB(0,255,255), // 17 - 20
|
|
|
|
RGB(64,0,0), RGB(64,0,128), RGB(64,0,192), RGB(0,0,255), // 21
|
|
RGB(64,64,0), RGB(64,64,128), RGB(64,64,192), RGB(64,64,255),
|
|
RGB(64,128,0), RGB(64,128,128), RGB(64,128,192), RGB(64,128,255),
|
|
RGB(64,192,0), RGB(64,192,128), RGB(64,192,192), RGB(64,192,255),
|
|
RGB(64,255,0), RGB(64,255,128), RGB(64,255,192), RGB(64,255,255),
|
|
|
|
RGB(128,0,0), RGB(128,0,128), RGB(128,0,192), RGB(128,0,255), // 41
|
|
RGB(128,64,0), RGB(128,64,128), RGB(128,64,192), RGB(128,64,255),
|
|
RGB(128,128,0), RGB(128,128,128), RGB(128,128,192), RGB(128,128,255),
|
|
RGB(128,192,0), RGB(128,192,128), RGB(128,192,192), RGB(128,192,255),
|
|
RGB(128,255,0), RGB(128,255,128), RGB(128,255,192), RGB(128,255,255),
|
|
|
|
RGB(192,0,0), RGB(192,0,128), RGB(192,0,192), RGB(192,0,255), // 61
|
|
RGB(192,64,0), RGB(192,64,128), RGB(192,64,192), RGB(192,64,255),
|
|
RGB(192,128,0), RGB(192,128,128), RGB(192,128,192), RGB(192,128,255),
|
|
RGB(192,192,0), RGB(192,192,128), RGB(192,192,192), RGB(192,192,255),
|
|
RGB(192,255,0), RGB(192,255,128), RGB(192,255,192), RGB(192,255,255),
|
|
|
|
RGB(255,0,0), RGB(255,0,128), RGB(255,0,192), RGB(255,0,255), // 81
|
|
RGB(255,64,0), RGB(255,64,128), RGB(255,64,192), RGB(255,64,255),
|
|
RGB(255,128,0), RGB(255,128,128), RGB(255,128,192), RGB(255,128,255),
|
|
RGB(255,192,0), RGB(255,192,128), RGB(255,192,192), RGB(255,192,255),
|
|
RGB(255,255,0), RGB(255,255,128), RGB(255,255,192), RGB(255,255,255) // 100 ?
|
|
};
|
|
|
|
|
|
#define InputBoxHeight 25
|
|
static LRESULT CALLBACK ConsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
|
static LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ;
|
|
static LRESULT APIENTRY OutputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ;
|
|
static LRESULT APIENTRY MonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ;
|
|
void MoveWindows(struct ConsoleInfo * Cinfo);
|
|
VOID CloseConsoleSupport(struct ConsoleInfo * Cinfo);
|
|
VOID AddLinetoWindow(struct ConsoleInfo * Cinfo, WCHAR * Line);
|
|
VOID DoRefresh(struct ConsoleInfo * Cinfo);
|
|
|
|
void ChatFlush(ChatCIRCUIT * conn);
|
|
char * lookupuser(char * call);
|
|
|
|
VOID SaveIntValue(char * Key, int Value);
|
|
VOID SaveStringValue(char * Key, char * Value);
|
|
int GetIntValue(char * Key, int Default);
|
|
VOID GetStringValue(char * Key, char * Value, int Len);
|
|
int ChatIsUTF8(unsigned char *ptr, int len);
|
|
|
|
|
|
#define BGCOLOUR RGB(236,233,216)
|
|
|
|
extern int Bells, FlashOnBell, StripLF, WarnWrap, WrapInput, FlashOnConnect, CloseWindowOnBye;
|
|
|
|
char Version[32];
|
|
char ConsoleSize[32];
|
|
char MonitorSize[32];
|
|
char DebugSize[32];
|
|
char WindowSize[32];
|
|
|
|
RECT ConsoleRect;
|
|
|
|
|
|
HMENU trayMenu = 0;
|
|
|
|
BOOL CreateConsole(int Stream)
|
|
{
|
|
WNDCLASS wc = {0};
|
|
HBRUSH bgBrush;
|
|
HMENU hMenu;
|
|
char Size[80] = "";
|
|
char RTFColours[3000];
|
|
struct ConsoleInfo * Cinfo;
|
|
int i, n;
|
|
char Text[80];
|
|
|
|
if (Stream == -1)
|
|
Cinfo = &BBSConsole;
|
|
else
|
|
Cinfo = &ChatConsole;
|
|
|
|
InitHeader = Cinfo;
|
|
|
|
if (Cinfo->hConsole)
|
|
{
|
|
ShowWindow(Cinfo->hConsole, SW_SHOWNORMAL);
|
|
SetForegroundWindow(Cinfo->hConsole);
|
|
return FALSE; // Already open
|
|
}
|
|
|
|
memset(Cinfo, 0, sizeof(struct ConsoleInfo));
|
|
|
|
if (BBSConsole.next == NULL) BBSConsole.next = &ChatConsole;
|
|
|
|
Cinfo->BPQStream = Stream;
|
|
|
|
bgBrush = CreateSolidBrush(BGCOLOUR);
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = ConsWndProc;
|
|
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = DLGWINDOWEXTRA;
|
|
wc.hInstance = hInst;
|
|
wc.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(BPQICON) );
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = bgBrush;
|
|
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = ClassName;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
hConsole = CreateDialog(hInst,ClassName,0,NULL);
|
|
|
|
if (!hConsole)
|
|
return (FALSE);
|
|
|
|
wsprintf(Text, "Chat %s Console", Session);
|
|
SetWindowText(hConsole, Text);
|
|
|
|
Cinfo->readbuff = zalloc(2000);
|
|
Cinfo->readbufflen = 1000;
|
|
|
|
hMenu=GetMenu(hConsole);
|
|
Cinfo->hMenu = hMenu;
|
|
|
|
CheckMenuItem(hMenu,BPQBELLS, (Bells) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hMenu,BPQFLASHONBELL, (FlashOnBell) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hMenu,BPQStripLF, (StripLF) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hMenu,IDM_WARNINPUT, (WarnWrap) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hMenu,IDM_WRAPTEXT, (WrapInput) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hMenu,IDM_Flash, (FlashOnConnect) ? MF_CHECKED : MF_UNCHECKED);
|
|
CheckMenuItem(hMenu,IDM_CLOSEWINDOW, (CloseWindowOnBye) ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
DrawMenuBar(hWnd);
|
|
|
|
if (trayMenu == 0)
|
|
{
|
|
trayMenu = CreatePopupMenu();
|
|
AppendMenu(trayMenu,MF_STRING,40000,"Copy");
|
|
}
|
|
|
|
// Set up RTF Header, including Colours String;
|
|
|
|
memcpy(RTFColours, "{\\colortbl ;", 12);
|
|
n = 12;
|
|
|
|
for (i = 1; i < 100; i++)
|
|
{
|
|
COLORREF Colour = Colours[i];
|
|
n += wsprintf(&RTFColours[n], "\\red%d\\green%d\\blue%d;", GetRValue(Colour), GetGValue(Colour),GetBValue(Colour));
|
|
}
|
|
|
|
RTFColours[n++] = '}';
|
|
RTFColours[n] = 0;
|
|
|
|
strcpy(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fprq1 FixedSys;}}");
|
|
// strcpy(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fmodern\\fcharset204\\fprq1 FixedSys;}}");
|
|
strcat(RTFHeader, RTFColours);
|
|
strcat(RTFHeader, "\\viewkind4\\uc1\\pard\\f0");
|
|
|
|
sprintf(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fprq1\\cpg%d\\fcharset%d %s;}}", 0, 0, "Courier New");
|
|
sprintf(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fmodern\\fprq1;}}");
|
|
strcat(RTFHeader, RTFColours);
|
|
strcat(RTFHeader, "\\viewkind4\\uc1\\pard\\f0\\fs20\\uc0");
|
|
|
|
|
|
RTFHddrLen = strlen(RTFHeader);
|
|
|
|
// Create a Rich Text Control
|
|
|
|
Cinfo->SendHeader = TRUE;
|
|
Cinfo->Finished = TRUE;
|
|
Cinfo->CurrentColour = 1;
|
|
|
|
LoadLibrary("riched20.dll");
|
|
|
|
Cinfo->hwndOutput = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, "",
|
|
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | WS_VSCROLL | ES_READONLY,
|
|
6,145,290,130, hConsole, NULL, hInst, NULL);
|
|
|
|
// Register for Mouse Events for Copy/Paste
|
|
|
|
SendMessage(Cinfo->hwndOutput, EM_SETEVENTMASK, (WPARAM)0, (LPARAM)ENM_MOUSEEVENTS | ENM_SCROLLEVENTS | ENM_KEYEVENTS);
|
|
SendMessage(Cinfo->hwndOutput, EM_EXLIMITTEXT, 0, MAXLINES * LINELEN);
|
|
|
|
Cinfo->hwndInput = GetDlgItem(hConsole, 118);
|
|
|
|
// Set our own WndProcs for the controls.
|
|
|
|
Cinfo->wpOrigInputProc = (WNDPROC) SetWindowLong(Cinfo->hwndInput, GWL_WNDPROC, (LONG) InputProc);
|
|
|
|
if (cfgMinToTray)
|
|
{
|
|
char Text[80];
|
|
wsprintf(Text, "Chat %s Console", Session);
|
|
AddTrayMenuItem(hConsole, Text);
|
|
}
|
|
|
|
ShowWindow(hConsole, SW_SHOWNORMAL);
|
|
|
|
if (ConsoleRect.right < 100 || ConsoleRect.bottom < 100)
|
|
{
|
|
GetWindowRect(hConsole, &ConsoleRect);
|
|
}
|
|
|
|
MoveWindow(hConsole, ConsoleRect.left, ConsoleRect.top,
|
|
ConsoleRect.right-ConsoleRect.left,
|
|
ConsoleRect.bottom-ConsoleRect.top, TRUE);
|
|
|
|
Cinfo->hConsole = hConsole;
|
|
|
|
MoveWindows(Cinfo);
|
|
|
|
Cinfo->Console = zalloc(sizeof(ChatCIRCUIT));
|
|
|
|
Cinfo->Console->Active = TRUE;
|
|
Cinfo->Console->BPQStream = Stream;
|
|
|
|
strcpy(Cinfo->Console->Callsign, ChatSYSOPCall);
|
|
|
|
user = zalloc(sizeof(struct UserInfo));
|
|
|
|
strcpy(user->Call, ChatSYSOPCall);
|
|
|
|
Cinfo->Console->UserPointer = user;
|
|
Cinfo->Console->paclen=236;
|
|
Cinfo->Console->sysop = TRUE;
|
|
|
|
if (user->Name[0] == 0)
|
|
{
|
|
char * Name = lookupuser(user->Call);
|
|
|
|
if (Name)
|
|
{
|
|
if (strlen(Name) > 17)
|
|
Name[17] = 0;
|
|
|
|
strcpy(user->Name, Name);
|
|
free(Name);
|
|
}
|
|
else
|
|
{
|
|
Cinfo->Console->Flags |= GETTINGUSER;
|
|
SendUnbuffered(-2, NewUserPrompt, strlen(NewUserPrompt));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (rtloginu (Cinfo->Console, TRUE))
|
|
Cinfo->Console->Flags |= CHATMODE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID CloseConsole(int Stream)
|
|
{
|
|
struct ConsoleInfo * Cinfo;
|
|
|
|
for (Cinfo = ConsHeader[0]; Cinfo; Cinfo = Cinfo->next)
|
|
{
|
|
if (Cinfo->Console)
|
|
{
|
|
if (Cinfo->BPQStream == Stream)
|
|
{
|
|
CloseConsoleSupport(Cinfo);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID CloseConsoleSupport(struct ConsoleInfo * Cinfo)
|
|
{
|
|
if (Cinfo->Console->Flags & CHATMODE)
|
|
{
|
|
__try
|
|
{
|
|
logout(Cinfo->Console);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
}
|
|
|
|
Cinfo->Console->Flags = 0;
|
|
}
|
|
|
|
|
|
if (CloseWindowOnBye)
|
|
{
|
|
// PostMessage(hConsole, WM_DESTROY, 0, 0);
|
|
DestroyWindow(Cinfo->hConsole);
|
|
}
|
|
}
|
|
|
|
void MoveWindows(struct ConsoleInfo * Cinfo)
|
|
{
|
|
RECT rcClient;
|
|
int ClientWidth;
|
|
|
|
GetClientRect(Cinfo->hConsole, &rcClient);
|
|
|
|
if (rcClient.bottom == 0) // Minimised
|
|
return;
|
|
|
|
Cinfo->ClientHeight = rcClient.bottom;
|
|
ClientWidth = rcClient.right;
|
|
|
|
MoveWindow(Cinfo->hwndOutput,2, 2, ClientWidth-4, Cinfo->ClientHeight-InputBoxHeight-4, TRUE);
|
|
MoveWindow(Cinfo->hwndInput,2, Cinfo->ClientHeight-InputBoxHeight-2, ClientWidth-4, InputBoxHeight, TRUE);
|
|
|
|
GetClientRect(Cinfo->hwndOutput, &rcClient);
|
|
|
|
Cinfo->ClientHeight = rcClient.bottom;
|
|
ClientWidth = rcClient.right;
|
|
|
|
Cinfo->WarnLen = ClientWidth/8 - 1;
|
|
Cinfo->WrapLen = Cinfo->WarnLen;
|
|
Cinfo->maxlinelen = Cinfo->WarnLen;
|
|
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK ChatColourDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
TEXTMETRIC tm;
|
|
int y;
|
|
LPMEASUREITEMSTRUCT lpmis;
|
|
LPDRAWITEMSTRUCT lpdis;
|
|
|
|
|
|
switch (message)
|
|
{
|
|
int Colour;
|
|
USER *user;
|
|
char Call[100];
|
|
int Sel;
|
|
char ColourString[100];
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
for (user = user_hd; user; user = user->next)
|
|
{
|
|
SendDlgItemMessage(hDlg, IDC_CHATCALLS, CB_ADDSTRING, 0, (LPARAM) user->call);
|
|
}
|
|
|
|
for (Colour = 0; Colour < 100; Colour++)
|
|
{
|
|
SendDlgItemMessage(hDlg, IDC_CHATCOLOURS, CB_ADDSTRING, 0, (LPARAM) Colours [Colour]);
|
|
}
|
|
return TRUE;
|
|
|
|
|
|
case WM_MEASUREITEM:
|
|
|
|
lpmis = (LPMEASUREITEMSTRUCT) lParam;
|
|
|
|
// Set the height of the list box items.
|
|
|
|
lpmis->itemHeight = 15;
|
|
return TRUE;
|
|
|
|
case WM_DRAWITEM:
|
|
|
|
lpdis = (LPDRAWITEMSTRUCT) lParam;
|
|
|
|
// If there are no list box items, skip this message.
|
|
|
|
if (lpdis->itemID == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
switch (lpdis->itemAction)
|
|
{
|
|
case ODA_SELECT:
|
|
case ODA_DRAWENTIRE:
|
|
|
|
// if Chat Console, and message has a colour eacape, action it
|
|
|
|
GetTextMetrics(lpdis->hDC, &tm);
|
|
|
|
y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2;
|
|
|
|
SetTextColor(lpdis->hDC, Colours[lpdis->itemID]);
|
|
|
|
// SetBkColor(lpdis->hDC, 0);
|
|
|
|
wsprintf(ColourString, "XXXXXX %06X", Colours[lpdis->itemID]);
|
|
|
|
TextOut(lpdis->hDC,
|
|
6,
|
|
y,
|
|
ColourString,
|
|
13);
|
|
|
|
// SetTextColor(lpdis->hDC, OldColour);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch LOWORD(wParam)
|
|
{
|
|
case IDC_CHATCALLS:
|
|
|
|
if (HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
Sel = SendDlgItemMessage(hDlg, IDC_CHATCALLS, CB_GETCURSEL, 0, 0);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_CHATCALLS, CB_GETLBTEXT, Sel, (LPARAM)(LPCTSTR)&Call);
|
|
|
|
user = user_find(Call, NULL);
|
|
|
|
if (user)
|
|
SendDlgItemMessage(hDlg, IDC_CHATCOLOURS, CB_SETCURSEL, user->Colour - 10, 0);
|
|
}
|
|
|
|
break;
|
|
|
|
case IDOK:
|
|
|
|
Sel = SendDlgItemMessage(hDlg, IDC_CHATCALLS, CB_GETCURSEL, 0, 0);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_CHATCALLS, CB_GETLBTEXT, Sel, (LPARAM)(LPCTSTR)&Call);
|
|
|
|
Sel = SendDlgItemMessage(hDlg, IDC_CHATCOLOURS, CB_GETCURSEL, 0, 0);
|
|
|
|
user = user_find(Call, NULL);
|
|
|
|
if (user)
|
|
{
|
|
user->Colour = Sel + 10;
|
|
upduser(user);
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
LRESULT CALLBACK ConsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int wmId, wmEvent;
|
|
LPRECT lprc;
|
|
int i;
|
|
struct ConsoleInfo * Cinfo;
|
|
UCHAR tchBuffer[100000];
|
|
UCHAR * buf = tchBuffer;
|
|
TEXTMETRIC tm;
|
|
int y;
|
|
LPMEASUREITEMSTRUCT lpmis;
|
|
LPDRAWITEMSTRUCT lpdis;
|
|
|
|
for (Cinfo = ConsHeader[0]; Cinfo; Cinfo = Cinfo->next)
|
|
{
|
|
if (Cinfo->hConsole == hWnd)
|
|
break;
|
|
}
|
|
|
|
if (Cinfo == NULL)
|
|
Cinfo = InitHeader;
|
|
|
|
switch (message) {
|
|
|
|
case WM_CTLCOLOREDIT:
|
|
|
|
if (Cinfo->Scrolled)
|
|
{
|
|
HDC hdcStatic = (HDC)wParam;
|
|
SetBkMode(hdcStatic, TRANSPARENT);
|
|
|
|
return (LONG)GetStockObject(LTGRAY_BRUSH);
|
|
}
|
|
return (DefWindowProc(hWnd, message, wParam, lParam));
|
|
|
|
|
|
case WM_VSCROLL:
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
const MSGFILTER * pF = (MSGFILTER *)lParam;
|
|
POINT pos;
|
|
CHARRANGE Range;
|
|
|
|
if(pF->nmhdr.hwndFrom == Cinfo->hwndOutput)
|
|
{
|
|
if(pF->msg == WM_VSCROLL)
|
|
{
|
|
// int Command = LOWORD(pF->wParam);
|
|
// int Pos = HIWORD(pF->wParam);
|
|
|
|
// Cinfo->Thumb = SendMessage(Cinfo->hwndOutput, EM_GETTHUMB, 0, 0);
|
|
|
|
DoRefresh(Cinfo);
|
|
break;
|
|
}
|
|
|
|
if(pF->msg == WM_KEYUP)
|
|
{
|
|
if (pF->wParam == VK_PRIOR || pF->wParam == VK_NEXT)
|
|
{
|
|
// Cinfo->Thumb = SendMessage(Cinfo->hwndOutput, EM_GETTHUMB, 0, 0);
|
|
DoRefresh(Cinfo);
|
|
}
|
|
}
|
|
|
|
if(pF->msg == WM_RBUTTONDOWN)
|
|
{
|
|
// Only allow popup if something is selected
|
|
|
|
SendMessage(Cinfo->hwndOutput, EM_EXGETSEL , 0, (WPARAM)&Range);
|
|
if (Range.cpMin == Range.cpMax)
|
|
return TRUE;
|
|
|
|
GetCursorPos(&pos);
|
|
TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, hWnd, 0);
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_MEASUREITEM:
|
|
|
|
lpmis = (LPMEASUREITEMSTRUCT) lParam;
|
|
|
|
// Set the height of the list box items.
|
|
|
|
lpmis->itemHeight = 15;
|
|
return TRUE;
|
|
|
|
case WM_DRAWITEM:
|
|
|
|
lpdis = (LPDRAWITEMSTRUCT) lParam;
|
|
|
|
// If there are no list box items, skip this message.
|
|
|
|
if (lpdis->itemID == -1)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
switch (lpdis->itemAction)
|
|
{
|
|
case ODA_SELECT:
|
|
case ODA_DRAWENTIRE:
|
|
|
|
// if Chat Console, and message has a colour eacape, action it
|
|
|
|
SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM) tchBuffer);
|
|
|
|
GetTextMetrics(lpdis->hDC, &tm);
|
|
|
|
y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2;
|
|
|
|
if ((Cinfo->BPQStream == -2) && (tchBuffer[0] == 0x1b))
|
|
{
|
|
SetTextColor(lpdis->hDC, Colours[tchBuffer[1] - 10]);
|
|
buf += 2;
|
|
}
|
|
// SetBkColor(lpdis->hDC, 0);
|
|
|
|
TextOut(lpdis->hDC,
|
|
6,
|
|
y,
|
|
buf,
|
|
strlen(buf));
|
|
|
|
// SetTextColor(lpdis->hDC, OldColour);
|
|
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
|
|
case WM_ACTIVATE:
|
|
|
|
SetFocus(Cinfo->hwndInput);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
|
|
wmId = LOWORD(wParam); // Remember, these are...
|
|
wmEvent = HIWORD(wParam); // ...different for Win32!
|
|
|
|
switch (wmId) {
|
|
|
|
case 40000:
|
|
{
|
|
int len=0;
|
|
HGLOBAL hMem;
|
|
char * ptr;
|
|
CHARRANGE Range;
|
|
|
|
// Copy Rich Text Selection to Clipboard
|
|
|
|
SendMessage(Cinfo->hwndOutput, EM_EXGETSEL , 0, (WPARAM)&Range);
|
|
|
|
hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, Range.cpMax - Range.cpMin + 1);
|
|
|
|
if (hMem != 0)
|
|
{
|
|
ptr=GlobalLock(hMem);
|
|
|
|
if (OpenClipboard(Cinfo->hConsole))
|
|
{
|
|
len = SendMessage(Cinfo->hwndOutput, EM_GETSELTEXT , 0, (WPARAM)ptr);
|
|
|
|
GlobalUnlock(hMem);
|
|
EmptyClipboard();
|
|
SetClipboardData(CF_TEXT,hMem);
|
|
CloseClipboard();
|
|
}
|
|
}
|
|
else
|
|
GlobalFree(hMem);
|
|
|
|
SetFocus(Cinfo->hwndInput);
|
|
}
|
|
|
|
|
|
|
|
|
|
case BPQBELLS:
|
|
|
|
ToggleParam(Cinfo->hMenu, hWnd, &Bells, BPQBELLS);
|
|
break;
|
|
|
|
case BPQFLASHONBELL:
|
|
|
|
ToggleParam(Cinfo->hMenu, hWnd, &FlashOnBell, BPQFLASHONBELL);
|
|
break;
|
|
|
|
case BPQStripLF:
|
|
|
|
ToggleParam(Cinfo->hMenu, hWnd, &StripLF, BPQStripLF);
|
|
break;
|
|
|
|
case IDM_WARNINPUT:
|
|
|
|
ToggleParam(Cinfo->hMenu, hWnd, &WarnWrap, IDM_WARNINPUT);
|
|
break;
|
|
|
|
|
|
case IDM_WRAPTEXT:
|
|
|
|
ToggleParam(Cinfo->hMenu, hWnd, &WrapInput, IDM_WRAPTEXT);
|
|
break;
|
|
|
|
case IDM_Flash:
|
|
|
|
ToggleParam(Cinfo->hMenu, hWnd, &FlashOnConnect, IDM_Flash);
|
|
break;
|
|
|
|
case IDM_CLOSEWINDOW:
|
|
|
|
ToggleParam(Cinfo->hMenu, hWnd, &CloseWindowOnBye, IDM_CLOSEWINDOW);
|
|
break;
|
|
|
|
case BPQCLEAROUT:
|
|
|
|
for (i = 0; i < MAXLINES; i++)
|
|
{
|
|
Cinfo->OutputScreen[i][0] = 0;
|
|
}
|
|
|
|
Cinfo->CurrentLine = 0;
|
|
DoRefresh(Cinfo);
|
|
break;
|
|
|
|
|
|
SendMessage(Cinfo->hwndOutput,LB_RESETCONTENT, 0, 0);
|
|
break;
|
|
|
|
case BPQCOPYOUT:
|
|
|
|
CopyRichTextToClipboard(Cinfo->hwndOutput);
|
|
break;
|
|
|
|
|
|
case IDM_EDITCHATCOLOURS:
|
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_CHATCOLCONFIG), hWnd, ChatColourDialogProc);
|
|
break;
|
|
|
|
|
|
//case BPQHELP:
|
|
|
|
// HtmlHelp(hWnd,"BPQTerminal.chm",HH_HELP_FINDER,0);
|
|
// break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
|
|
wmId = LOWORD(wParam); // Remember, these are...
|
|
wmEvent = HIWORD(wParam); // ...different for Win32!
|
|
|
|
switch (wmId) {
|
|
|
|
case SC_MINIMIZE:
|
|
|
|
if (cfgMinToTray)
|
|
return ShowWindow(hWnd, SW_HIDE);
|
|
|
|
default:
|
|
|
|
return (DefWindowProc(hWnd, message, wParam, lParam));
|
|
}
|
|
|
|
|
|
case WM_SIZING:
|
|
|
|
lprc = (LPRECT) lParam;
|
|
|
|
Cinfo->Height = lprc->bottom-lprc->top;
|
|
Cinfo->Width = lprc->right-lprc->left;
|
|
|
|
MoveWindows(Cinfo);
|
|
|
|
return TRUE;
|
|
|
|
case WM_SIZE:
|
|
|
|
MoveWindows(Cinfo);
|
|
return TRUE;
|
|
|
|
case WM_CLOSE:
|
|
|
|
CloseConsoleSupport(Cinfo);
|
|
|
|
return (DefWindowProc(hWnd, message, wParam, lParam));
|
|
|
|
case WM_DESTROY:
|
|
|
|
// Remove the subclass from the edit control.
|
|
|
|
GetWindowRect(hWnd, &ConsoleRect); // For save soutine
|
|
|
|
SetWindowLong(Cinfo->hwndInput, GWL_WNDPROC,
|
|
(LONG) Cinfo->wpOrigInputProc);
|
|
|
|
|
|
if (cfgMinToTray)
|
|
DeleteTrayMenuItem(hWnd);
|
|
|
|
|
|
if (Cinfo->Console && Cinfo->Console->Active)
|
|
{
|
|
ChatClearQueue(Cinfo->Console);
|
|
|
|
Cinfo->Console->Active = FALSE;
|
|
RefreshMainWindow();
|
|
logout(Cinfo->Console);
|
|
}
|
|
|
|
// Free Scrollback
|
|
|
|
for (i = 0; i < MAXSTACK ; i++)
|
|
{
|
|
if (Cinfo->KbdStack[i])
|
|
{
|
|
free(Cinfo->KbdStack[i]);
|
|
Cinfo->KbdStack[i] = NULL;
|
|
}
|
|
}
|
|
|
|
Sleep(500);
|
|
|
|
free(Cinfo->readbuff);
|
|
Cinfo->readbufflen = 0;
|
|
|
|
free(Cinfo->Console);
|
|
Cinfo->Console = 0;
|
|
Cinfo->hConsole = NULL;
|
|
|
|
break;
|
|
|
|
default:
|
|
return (DefWindowProc(hWnd, message, wParam, lParam));
|
|
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
|
|
LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int i;
|
|
unsigned int TextLen;
|
|
struct ConsoleInfo * Cinfo;
|
|
|
|
for (Cinfo = ConsHeader[0]; Cinfo; Cinfo = Cinfo->next)
|
|
{
|
|
if (Cinfo->hwndInput == hwnd)
|
|
break;
|
|
}
|
|
|
|
if (Cinfo == NULL)
|
|
Cinfo = InitHeader;
|
|
|
|
|
|
if (uMsg == WM_KEYUP)
|
|
{
|
|
unsigned int i;
|
|
// Debugprintf("5%x", LOBYTE(HIWORD(lParam)));
|
|
|
|
if (LOBYTE(HIWORD(lParam)) == 0x48 && wParam == 0x26)
|
|
{
|
|
// Scroll up
|
|
|
|
if (Cinfo->KbdStack[Cinfo->StackIndex] == NULL)
|
|
return TRUE;
|
|
|
|
SendMessage(Cinfo->hwndInput, WM_SETTEXT,0,(LPARAM)(LPCSTR) Cinfo->KbdStack[Cinfo->StackIndex]);
|
|
|
|
for (i = 0; i < strlen(Cinfo->KbdStack[Cinfo->StackIndex]); i++)
|
|
{
|
|
SendMessage(Cinfo->hwndInput, WM_KEYDOWN, VK_RIGHT, 0);
|
|
SendMessage(Cinfo->hwndInput, WM_KEYUP, VK_RIGHT, 0);
|
|
}
|
|
|
|
Cinfo->StackIndex++;
|
|
if (Cinfo->StackIndex == 20)
|
|
Cinfo->StackIndex = 19;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (LOBYTE(HIWORD(lParam)) == 0x50 && wParam == 0x28)
|
|
{
|
|
// Scroll up
|
|
|
|
Cinfo->StackIndex--;
|
|
if (Cinfo->StackIndex < 0)
|
|
Cinfo->StackIndex = 0;
|
|
|
|
if (Cinfo->KbdStack[Cinfo->StackIndex] == NULL)
|
|
return TRUE;
|
|
|
|
SendMessage(Cinfo->hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) Cinfo->KbdStack[Cinfo->StackIndex]);
|
|
|
|
for (i = 0; i < strlen(Cinfo->KbdStack[Cinfo->StackIndex]); i++)
|
|
{
|
|
SendMessage(Cinfo->hwndInput, WM_KEYDOWN, VK_RIGHT, 0);
|
|
SendMessage(Cinfo->hwndInput, WM_KEYUP, VK_RIGHT, 0);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
if (uMsg == WM_CHAR)
|
|
{
|
|
TextLen = SendMessage(Cinfo->hwndInput,WM_GETTEXTLENGTH, 0, 0);
|
|
|
|
if (TextLen > INPUTLEN-10) Beep(220, 150);
|
|
|
|
if(WarnWrap || WrapInput)
|
|
{
|
|
TextLen = SendMessage(Cinfo->hwndInput,WM_GETTEXTLENGTH, 0, 0);
|
|
|
|
if (WarnWrap)
|
|
if (TextLen == Cinfo->WarnLen) Beep(220, 150);
|
|
|
|
if (WrapInput)
|
|
if ((wParam == 0x20) && (TextLen > Cinfo->WrapLen))
|
|
wParam = 13; // Replace space with Enter
|
|
|
|
}
|
|
|
|
if (wParam == 13)
|
|
{
|
|
Cinfo->kbptr=SendMessage(Cinfo->hwndInput, WM_GETTEXT, INPUTLEN-1,
|
|
(LPARAM) (LPCSTR)Cinfo->kbbuf);
|
|
|
|
Cinfo->StackIndex = 0;
|
|
|
|
// Stack it
|
|
|
|
if (Cinfo->KbdStack[19])
|
|
free(Cinfo->KbdStack[19]);
|
|
|
|
for (i = 18; i >= 0; i--)
|
|
{
|
|
Cinfo->KbdStack[i+1] = Cinfo->KbdStack[i];
|
|
}
|
|
|
|
Cinfo->KbdStack[0] = _strdup(Cinfo->kbbuf);
|
|
|
|
Cinfo->kbbuf[Cinfo->kbptr]=13;
|
|
|
|
// Echo
|
|
|
|
if (Cinfo->BPQStream == -2)
|
|
{
|
|
UCHAR Msg[INPUTLEN * 2]; // Should be plenty
|
|
Msg[0] = 0x1b;
|
|
Msg[1] = 11;
|
|
|
|
memcpy(&Msg[2], Cinfo->kbbuf, Cinfo->kbptr+1);
|
|
WritetoConsoleWindow(Cinfo->BPQStream, Msg, Cinfo->kbptr+3);
|
|
}
|
|
else
|
|
WritetoConsoleWindow(Cinfo->BPQStream, Cinfo->kbbuf, Cinfo->kbptr+1);
|
|
|
|
if (Cinfo->Scrolled)
|
|
{
|
|
POINT Point;
|
|
Point.x = 0;
|
|
Point.y = 25000; // Should be plenty for any font
|
|
|
|
SendMessage(Cinfo->hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point);
|
|
Cinfo->Scrolled = FALSE;
|
|
}
|
|
|
|
DoRefresh(Cinfo);
|
|
ProcessLine(Cinfo->Console, user, &Cinfo->kbbuf[0], Cinfo->kbptr+1);
|
|
|
|
SendMessage(Cinfo->hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) "");
|
|
|
|
return 0;
|
|
}
|
|
if (wParam == 0x1a) // Ctrl/Z
|
|
{
|
|
|
|
Cinfo->kbbuf[0]=0x1a;
|
|
Cinfo->kbbuf[1]=13;
|
|
|
|
ProcessLine(Cinfo->Console, user, &Cinfo->kbbuf[0], 2);
|
|
|
|
|
|
SendMessage(Cinfo->hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) "");
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
return CallWindowProc(Cinfo->wpOrigInputProc, hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
|
|
int WritetoConsoleWindowSupport(struct ConsoleInfo * Cinfo, WCHAR * Msg, int len);
|
|
|
|
int WritetoConsoleWindow(int Stream, UCHAR * Msg, int len)
|
|
{
|
|
struct ConsoleInfo * Cinfo;
|
|
WCHAR BufferW[65536];
|
|
|
|
int wlen;
|
|
|
|
if (ChatIsUTF8(Msg, len))
|
|
wlen = MultiByteToWideChar(CP_UTF8, 0, Msg, len, BufferW, 65536);
|
|
else
|
|
wlen = MultiByteToWideChar(CP_ACP, 0, Msg, len, BufferW, 65536);
|
|
|
|
for (Cinfo = ConsHeader[0]; Cinfo; Cinfo = Cinfo->next)
|
|
{
|
|
if (Cinfo->Console)
|
|
{
|
|
if (Cinfo->BPQStream == Stream)
|
|
{
|
|
WritetoConsoleWindowSupport(Cinfo, BufferW, wlen);
|
|
DoRefresh(Cinfo);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int WritetoConsoleWindowSupport(struct ConsoleInfo * Cinfo, WCHAR * Msg, int len)
|
|
{
|
|
WCHAR * ptr1, * ptr2;
|
|
|
|
if (len + Cinfo->PartLinePtr > Cinfo->readbufflen)
|
|
{
|
|
Cinfo->readbufflen += len + Cinfo->PartLinePtr;
|
|
Cinfo->readbuff = realloc(Cinfo->readbuff, Cinfo->readbufflen * 2);
|
|
}
|
|
|
|
if (Cinfo->PartLinePtr != 0)
|
|
{
|
|
Cinfo->CurrentLine--; // Overwrite part line in buffer
|
|
if (Cinfo->CurrentLine < 0)
|
|
Cinfo->CurrentLine = MAXLINES - 1;
|
|
|
|
if (Msg[0] == 0x1b && len > 1)
|
|
{
|
|
Msg += 2; // Remove Colour Escape
|
|
len -= 2;
|
|
}
|
|
}
|
|
|
|
memcpy(&Cinfo->readbuff[Cinfo->PartLinePtr], Msg, len * 2);
|
|
|
|
len=len+Cinfo->PartLinePtr;
|
|
|
|
ptr1=&Cinfo->readbuff[0];
|
|
Cinfo->readbuff[len]=0;
|
|
|
|
if (Bells)
|
|
{
|
|
do {
|
|
|
|
ptr2=memchr(ptr1,7 , len * 2);
|
|
|
|
if (ptr2)
|
|
{
|
|
*(ptr2)=32;
|
|
|
|
if (FlashOnBell)
|
|
FlashWindow(Cinfo->hConsole, TRUE);
|
|
else
|
|
Beep(440,250);
|
|
}
|
|
|
|
} while (ptr2);
|
|
}
|
|
|
|
lineloop:
|
|
|
|
if (len > 0)
|
|
{
|
|
// copy text to control a line at a time
|
|
|
|
ptr2=memchr(ptr1, 13, len * 2);
|
|
|
|
if (ptr2 == 0)
|
|
{
|
|
// no newline. Move data to start of buffer and Save pointer
|
|
|
|
Cinfo->PartLinePtr = len;
|
|
memmove(Cinfo->readbuff, ptr1, len * 2);
|
|
AddLinetoWindow(Cinfo, ptr1);
|
|
// InvalidateRect(Cinfo->hwndOutput, NULL, FALSE);
|
|
|
|
return (0);
|
|
}
|
|
|
|
*(ptr2++)=0;
|
|
|
|
// If len is greater that screen with, fold
|
|
|
|
if ((ptr2 - ptr1) > Cinfo->maxlinelen)
|
|
{
|
|
WCHAR * ptr3;
|
|
WCHAR * saveptr1 = ptr1;
|
|
int linelen = ptr2 - ptr1;
|
|
int foldlen;
|
|
WCHAR save;
|
|
|
|
foldloop:
|
|
|
|
ptr3 = ptr1 + Cinfo->maxlinelen;
|
|
|
|
while(*ptr3!= 0x20 && ptr3 > ptr1)
|
|
{
|
|
ptr3--;
|
|
}
|
|
|
|
foldlen = ptr3 - ptr1 ;
|
|
|
|
if (foldlen == 0)
|
|
{
|
|
// No space before, so split at width
|
|
|
|
foldlen = Cinfo->maxlinelen;
|
|
ptr3 = ptr1 + Cinfo->maxlinelen;
|
|
|
|
}
|
|
else
|
|
{
|
|
ptr3++ ; // Omit space
|
|
linelen--;
|
|
}
|
|
save = ptr1[foldlen];
|
|
ptr1[foldlen] = 0;
|
|
AddLinetoWindow(Cinfo, ptr1);
|
|
ptr1[foldlen] = save;
|
|
linelen -= foldlen;
|
|
ptr1 = ptr3;
|
|
|
|
if (linelen > Cinfo->maxlinelen)
|
|
goto foldloop;
|
|
|
|
AddLinetoWindow(Cinfo, ptr1);
|
|
|
|
ptr1 = saveptr1;
|
|
}
|
|
else
|
|
AddLinetoWindow(Cinfo, ptr1);
|
|
|
|
Cinfo->PartLinePtr=0;
|
|
|
|
len-=(ptr2-ptr1);
|
|
|
|
ptr1=ptr2;
|
|
|
|
if ((len > 0) && StripLF)
|
|
{
|
|
if (*ptr1 == 0x0a) // Line Feed
|
|
{
|
|
ptr1++;
|
|
len--;
|
|
}
|
|
}
|
|
|
|
goto lineloop;
|
|
}
|
|
|
|
|
|
return (0);
|
|
}
|
|
|
|
int ToggleParam(HMENU hMenu, HWND hWnd, BOOL * Param, int Item)
|
|
{
|
|
*Param = !(*Param);
|
|
|
|
CheckMenuItem(hMenu,Item, (*Param) ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
return (0);
|
|
}
|
|
|
|
void CopyRichTextToClipboard(HWND hWnd)
|
|
{
|
|
int len=0;
|
|
HGLOBAL hMem;
|
|
char * ptr;
|
|
|
|
// Copy Rich Text to Clipboard
|
|
|
|
len = SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0);
|
|
|
|
hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len + 1);
|
|
|
|
if (hMem != 0)
|
|
{
|
|
ptr=GlobalLock(hMem);
|
|
|
|
if (OpenClipboard(MainWnd))
|
|
{
|
|
len = SendMessage(hWnd, WM_GETTEXT , len, (LPARAM)ptr);
|
|
|
|
GlobalUnlock(hMem);
|
|
EmptyClipboard();
|
|
SetClipboardData(CF_TEXT,hMem);
|
|
CloseClipboard();
|
|
}
|
|
}
|
|
else
|
|
GlobalFree(hMem);
|
|
}
|
|
|
|
|
|
void CopyToClipboard(HWND hWnd)
|
|
{
|
|
int i,n, len=0;
|
|
HGLOBAL hMem;
|
|
char * ptr;
|
|
//
|
|
// Copy List Box to clipboard
|
|
//
|
|
|
|
n = SendMessage(hWnd, LB_GETCOUNT, 0, 0);
|
|
|
|
for (i=0; i<n; i++)
|
|
{
|
|
len+=SendMessage(hWnd, LB_GETTEXTLEN, i, 0);
|
|
}
|
|
|
|
hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len+n+n+1);
|
|
|
|
|
|
if (hMem != 0)
|
|
{
|
|
ptr=GlobalLock(hMem);
|
|
|
|
if (OpenClipboard(MainWnd))
|
|
{
|
|
// CopyScreentoBuffer(GlobalLock(hMem));
|
|
|
|
for (i=0; i<n; i++)
|
|
{
|
|
ptr+=SendMessage(hWnd, LB_GETTEXT, i, (LPARAM) ptr);
|
|
*(ptr++)=13;
|
|
*(ptr++)=10;
|
|
}
|
|
|
|
*(ptr)=0; // end of data
|
|
|
|
GlobalUnlock(hMem);
|
|
EmptyClipboard();
|
|
SetClipboardData(CF_TEXT,hMem);
|
|
CloseClipboard();
|
|
}
|
|
else
|
|
GlobalFree(hMem);
|
|
}
|
|
}
|
|
|
|
VOID wcstoRTF(char * out, WCHAR * in)
|
|
{
|
|
WCHAR * ptr1 = in;
|
|
char * ptr2 = out;
|
|
int val = *ptr1++;
|
|
|
|
while (val)
|
|
{
|
|
{
|
|
if (val > 127 || val < -128 )
|
|
ptr2 += sprintf(ptr2, "\\u%d ", val);
|
|
else
|
|
*(ptr2++) = val;
|
|
}
|
|
val = *ptr1++;
|
|
}
|
|
*ptr2 = 0;
|
|
}
|
|
|
|
|
|
DWORD CALLBACK EditStreamCallback(struct ConsoleInfo * Cinfo, LPBYTE lpBuff, LONG cb, PLONG pcb)
|
|
{
|
|
int ReqLen = cb;
|
|
int i;
|
|
int Line;
|
|
char LineB[4096];
|
|
|
|
// if (cb != 4092)
|
|
// return 0;
|
|
|
|
if (Cinfo->SendHeader)
|
|
{
|
|
// Return header
|
|
|
|
memcpy(lpBuff, RTFHeader, RTFHddrLen);
|
|
*pcb = RTFHddrLen;
|
|
Cinfo->SendHeader = FALSE;
|
|
Cinfo->Finished = FALSE;
|
|
Cinfo->Index = 0;
|
|
return 0;
|
|
}
|
|
|
|
if (Cinfo->Finished)
|
|
{
|
|
*pcb = 0;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
if (BufferLen > cb)
|
|
{
|
|
memcpy(lpBuff, &Buffer[Offset], cb);
|
|
BufferLen -= cb;
|
|
Offset += cb;
|
|
*pcb = cb;
|
|
return 0;
|
|
}
|
|
|
|
memcpy(lpBuff, &Buffer[Offset], BufferLen);
|
|
|
|
*pcb = BufferLen;
|
|
*/
|
|
|
|
// Return 10 line at a time
|
|
|
|
for (i = 0; i < 10; i++);
|
|
{
|
|
Line = Cinfo->Index++ + Cinfo->CurrentLine - MAXLINES;
|
|
|
|
if (Line <0)
|
|
Line = Line + MAXLINES;
|
|
|
|
wcstoRTF(&LineB[0], Cinfo->OutputScreen[Line]);
|
|
|
|
sprintf(lpBuff, "\\cf%d ", Cinfo->Colourvalue[Line]);
|
|
strcat(lpBuff, LineB);
|
|
strcat(lpBuff, "\\line");
|
|
|
|
if (Cinfo->Index == MAXLINES)
|
|
{
|
|
Cinfo->Finished = TRUE;
|
|
strcat(lpBuff, "}");
|
|
i = 10;
|
|
}
|
|
}
|
|
*pcb = strlen(lpBuff);
|
|
return 0;
|
|
}
|
|
|
|
VOID DoRefresh(struct ConsoleInfo * Cinfo)
|
|
{
|
|
EDITSTREAM es = {0};
|
|
int Min, Max, Pos;
|
|
POINT Point;
|
|
SCROLLINFO ScrollInfo;
|
|
int LoopTrap = 0;
|
|
HWND hwndOutput = Cinfo->hwndOutput;
|
|
|
|
if(WINE)
|
|
Cinfo->Thumb = 30000;
|
|
else
|
|
Cinfo->Thumb = SendMessage(Cinfo->hwndOutput, EM_GETTHUMB, 0, 0);
|
|
|
|
Pos = Cinfo->Thumb + Cinfo->ClientHeight;
|
|
|
|
if ((Cinfo->Thumb + Cinfo->ClientHeight) > Cinfo->RTFHeight - 10) // Don't bother writing to screen if scrolled back
|
|
{
|
|
es.pfnCallback = (EDITSTREAMCALLBACK)EditStreamCallback;
|
|
es.dwCookie = (DWORD_PTR)Cinfo;
|
|
Cinfo->SendHeader = TRUE;
|
|
SendMessage(hwndOutput, EM_STREAMIN, SF_RTF, (LPARAM)&es);
|
|
}
|
|
|
|
GetScrollRange(hwndOutput, SB_VERT, &Min, &Max);
|
|
ScrollInfo.cbSize = sizeof(ScrollInfo);
|
|
ScrollInfo.fMask = SIF_ALL;
|
|
|
|
GetScrollInfo(hwndOutput, SB_VERT, &ScrollInfo);
|
|
|
|
// Debugprintf("Pos %d Max %d Min %d nMax %d ClientH %d", Pos, Min, Max, ScrollInfo.nMax, Cinfo->ClientHeight);
|
|
|
|
if (Cinfo->FirstTime == FALSE)
|
|
{
|
|
// RTF Controls don't immediately scroll to end - don't know why.
|
|
|
|
Cinfo->FirstTime = TRUE;
|
|
Point.x = 0;
|
|
Point.y = 25000; // Should be plenty for any font
|
|
|
|
while (LoopTrap++ < 20)
|
|
{
|
|
SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point);
|
|
}
|
|
|
|
GetScrollRange(hwndOutput, SB_VERT, &Min, &Max); // Get Actual Height
|
|
Cinfo->RTFHeight = Max;
|
|
Point.x = 0;
|
|
Point.y = Cinfo->RTFHeight - ScrollInfo.nPage;
|
|
SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point);
|
|
Cinfo->Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0);
|
|
}
|
|
|
|
Point.x = 0;
|
|
Point.y = Cinfo->RTFHeight - ScrollInfo.nPage;
|
|
|
|
if (Cinfo->Thumb > (Point.y - 10)) // Don't Scroll if user has scrolled back
|
|
{
|
|
SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point);
|
|
|
|
if (Cinfo->Scrolled)
|
|
{
|
|
Cinfo->Scrolled = FALSE;
|
|
InvalidateRect(Cinfo->hwndInput, NULL, TRUE);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!Cinfo->Scrolled)
|
|
{
|
|
Cinfo->Scrolled = TRUE;
|
|
InvalidateRect(Cinfo->hwndInput, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
VOID AddLinetoWindow(struct ConsoleInfo * Cinfo, WCHAR * Line)
|
|
{
|
|
int Len = wcslen(Line);
|
|
WCHAR * ptr1 = Line;
|
|
WCHAR * ptr2;
|
|
int l, Index;
|
|
WCHAR LineCopy[LINELEN * 2];
|
|
|
|
if (Line[0] == 0x1b && Len > 1)
|
|
{
|
|
// Save Colour Char
|
|
|
|
Cinfo->CurrentColour = Line[1] - 10;
|
|
ptr1 +=2;
|
|
Len -= 2;
|
|
}
|
|
|
|
wcscpy(Cinfo->OutputScreen[Cinfo->CurrentLine], ptr1);
|
|
|
|
// Look for chars we need to escape (\ { })
|
|
|
|
ptr1 = Cinfo->OutputScreen[Cinfo->CurrentLine];
|
|
Index = 0;
|
|
ptr2 = wcschr(ptr1, L'\\'); // Look for Backslash first, as we may add some later
|
|
|
|
if (ptr2)
|
|
{
|
|
while (ptr2)
|
|
{
|
|
l = ++ptr2 - ptr1;
|
|
memcpy(&LineCopy[Index], ptr1, l * 2); // Copy Including found char
|
|
Index += l;
|
|
LineCopy[Index++] = '\\';
|
|
Len++;
|
|
ptr1 = ptr2;
|
|
ptr2 = wcschr(ptr1, '\\');
|
|
}
|
|
wcscpy(&LineCopy[Index], ptr1); // Copy in rest
|
|
wcscpy(Cinfo->OutputScreen[Cinfo->CurrentLine], LineCopy);
|
|
}
|
|
|
|
ptr1 = Cinfo->OutputScreen[Cinfo->CurrentLine];
|
|
Index = 0;
|
|
ptr2 = wcschr(ptr1, '{');
|
|
|
|
if (ptr2)
|
|
{
|
|
while (ptr2)
|
|
{
|
|
l = ptr2 - ptr1;
|
|
memcpy(&LineCopy[Index], ptr1, l * 2);
|
|
Index += l;
|
|
LineCopy[Index++] = '\\';
|
|
LineCopy[Index++] = '{';
|
|
Len++;
|
|
ptr1 = ++ptr2;
|
|
ptr2 = wcschr(ptr1, '{');
|
|
}
|
|
wcscpy(&LineCopy[Index], ptr1); // Copy in rest
|
|
wcscpy(Cinfo->OutputScreen[Cinfo->CurrentLine], LineCopy);
|
|
}
|
|
|
|
ptr1 = Cinfo->OutputScreen[Cinfo->CurrentLine];
|
|
Index = 0;
|
|
ptr2 = wcschr(ptr1, '}'); // Look for Backslash first, as we may add some later
|
|
|
|
if (ptr2)
|
|
{
|
|
while (ptr2)
|
|
{
|
|
l = ptr2 - ptr1;
|
|
memcpy(&LineCopy[Index], ptr1, l * 2); // Copy
|
|
Index += l;
|
|
LineCopy[Index++] = '\\';
|
|
LineCopy[Index++] = '}';
|
|
Len++;
|
|
ptr1 = ++ptr2;
|
|
ptr2 = wcschr(ptr1, '}');
|
|
}
|
|
wcscpy(&LineCopy[Index], ptr1); // Copy in rest
|
|
wcscpy(Cinfo->OutputScreen[Cinfo->CurrentLine], LineCopy);
|
|
}
|
|
|
|
|
|
Cinfo->Colourvalue[Cinfo->CurrentLine] = Cinfo->CurrentColour;
|
|
Cinfo->LineLen[Cinfo->CurrentLine++] = Len;
|
|
if (Cinfo->CurrentLine >= MAXLINES) Cinfo->CurrentLine = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
#define XBITMAP 80
|
|
#define YBITMAP 20
|
|
|
|
#define BUFFER MAX_PATH
|
|
|
|
HBITMAP hbmpPencil, hbmpCrayon, hbmpMarker, hbmpPen, hbmpFork;
|
|
HBITMAP hbmpPicture, hbmpOld;
|
|
|
|
void AddItem(HWND hwnd, LPSTR lpstr, HBITMAP hbmp)
|
|
{
|
|
int nItem;
|
|
|
|
nItem = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)lpstr);
|
|
SendMessage(hwnd, LB_SETITEMDATA, (WPARAM)nItem, (LPARAM)hbmp);
|
|
}
|
|
|
|
DWORD APIENTRY DlgDrawProc(
|
|
HWND hDlg, // window handle to dialog box
|
|
UINT message, // type of message
|
|
UINT wParam, // message-specific information
|
|
LONG lParam)
|
|
{
|
|
int nItem;
|
|
TCHAR tchBuffer[BUFFER];
|
|
HBITMAP hbmp;
|
|
HWND hListBox;
|
|
TEXTMETRIC tm;
|
|
int y;
|
|
HDC hdcMem;
|
|
LPMEASUREITEMSTRUCT lpmis;
|
|
LPDRAWITEMSTRUCT lpdis;
|
|
RECT rcBitmap;
|
|
HRESULT hr;
|
|
size_t * pcch;
|
|
|
|
switch (message)
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
// Load bitmaps.
|
|
|
|
hbmpPencil = LoadBitmap(hinst, MAKEINTRESOURCE(700));
|
|
hbmpCrayon = LoadBitmap(hinst, MAKEINTRESOURCE(701));
|
|
hbmpMarker = LoadBitmap(hinst, MAKEINTRESOURCE(702));
|
|
hbmpPen = LoadBitmap(hinst, MAKEINTRESOURCE(703));
|
|
hbmpFork = LoadBitmap(hinst, MAKEINTRESOURCE(704));
|
|
|
|
// Retrieve list box handle.
|
|
|
|
hListBox = GetDlgItem(hDlg, IDL_STUFF);
|
|
|
|
// Initialize the list box text and associate a bitmap
|
|
// with each list box item.
|
|
|
|
AddItem(hListBox, "pencil", hbmpPencil);
|
|
AddItem(hListBox, "crayon", hbmpCrayon);
|
|
AddItem(hListBox, "marker", hbmpMarker);
|
|
AddItem(hListBox, "pen", hbmpPen);
|
|
AddItem(hListBox, "fork", hbmpFork);
|
|
|
|
SetFocus(hListBox);
|
|
SendMessage(hListBox, LB_SETCURSEL, 0, 0);
|
|
return TRUE;
|
|
|
|
case WM_MEASUREITEM:
|
|
|
|
lpmis = (LPMEASUREITEMSTRUCT) lParam;
|
|
|
|
// Set the height of the list box items.
|
|
|
|
lpmis->itemHeight = 20;
|
|
return TRUE;
|
|
|
|
case WM_DRAWITEM:
|
|
|
|
lpdis = (LPDRAWITEMSTRUCT) lParam;
|
|
|
|
// If there are no list box items, skip this message.
|
|
|
|
if (lpdis->itemID == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Draw the bitmap and text for the list box item. Draw a
|
|
// rectangle around the bitmap if it is selected.
|
|
|
|
switch (lpdis->itemAction)
|
|
{
|
|
case ODA_SELECT:
|
|
case ODA_DRAWENTIRE:
|
|
|
|
// Display the bitmap associated with the item.
|
|
|
|
hbmpPicture =(HBITMAP)SendMessage(lpdis->hwndItem,
|
|
LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0);
|
|
|
|
hdcMem = CreateCompatibleDC(lpdis->hDC);
|
|
hbmpOld = SelectObject(hdcMem, hbmpPicture);
|
|
|
|
BitBlt(lpdis->hDC,
|
|
lpdis->rcItem.left, lpdis->rcItem.top,
|
|
lpdis->rcItem.right - lpdis->rcItem.left,
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top,
|
|
hdcMem, 0, 0, SRCCOPY);
|
|
|
|
// Display the text associated with the item.
|
|
|
|
SendMessage(lpdis->hwndItem, LB_GETTEXT,
|
|
lpdis->itemID, (LPARAM) tchBuffer);
|
|
|
|
GetTextMetrics(lpdis->hDC, &tm);
|
|
|
|
y = (lpdis->rcItem.bottom + lpdis->rcItem.top -
|
|
tm.tmHeight) / 2;
|
|
|
|
hr = StringCchLength(tchBuffer, BUFFER, pcch);
|
|
if (FAILED(hr))
|
|
{
|
|
// TODO: Handle error.
|
|
}
|
|
|
|
TextOut(lpdis->hDC,
|
|
XBITMAP + 6,
|
|
y,
|
|
tchBuffer,
|
|
pcch);
|
|
|
|
SelectObject(hdcMem, hbmpOld);
|
|
DeleteDC(hdcMem);
|
|
|
|
// Is the item selected?
|
|
|
|
if (lpdis->itemState & ODS_SELECTED)
|
|
{
|
|
// Set RECT coordinates to surround only the
|
|
// bitmap.
|
|
|
|
rcBitmap.left = lpdis->rcItem.left;
|
|
rcBitmap.top = lpdis->rcItem.top;
|
|
rcBitmap.right = lpdis->rcItem.left + XBITMAP;
|
|
rcBitmap.bottom = lpdis->rcItem.top + YBITMAP;
|
|
|
|
// Draw a rectangle around bitmap to indicate
|
|
// the selection.
|
|
|
|
DrawFocusRect(lpdis->hDC, &rcBitmap);
|
|
}
|
|
break;
|
|
|
|
case ODA_FOCUS:
|
|
|
|
// Do not process focus changes. The focus caret
|
|
// (outline rectangle) indicates the selection.
|
|
// The IDOK button indicates the final
|
|
// selection.
|
|
|
|
break;
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
// Get the selected item's text.
|
|
|
|
nItem = SendMessage(GetDlgItem(hDlg, IDL_STUFF),
|
|
LB_GETCURSEL, 0, (LPARAM) 0);
|
|
hbmp = SendMessage(GetDlgItem(hDlg, IDL_STUFF),
|
|
LB_GETITEMDATA, nItem, 0);
|
|
|
|
// If the item is not the correct answer, tell the
|
|
// user to try again.
|
|
//
|
|
// If the item is the correct answer, congratulate
|
|
// the user and destroy the dialog box.
|
|
|
|
if (hbmp != hbmpFork)
|
|
{
|
|
MessageBox(hDlg, "Try again!", "Oops", MB_OK);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
MessageBox(hDlg, "You're right!",
|
|
"Congratulations.", MB_OK);
|
|
|
|
// Fall through.
|
|
}
|
|
|
|
case IDCANCEL:
|
|
|
|
// Destroy the dialog box.
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
|
|
// Free any resources used by the bitmaps.
|
|
|
|
DeleteObject(hbmpPencil);
|
|
DeleteObject(hbmpCrayon);
|
|
DeleteObject(hbmpMarker);
|
|
DeleteObject(hbmpPen);
|
|
DeleteObject(hbmpFork);
|
|
|
|
return TRUE;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
*/
|