#include "irc.h" #include "window.h" #include "screen.h" #include "keys.h" #include "vars.h" #include #define TIMER_MINUTE 1 #define TIMER_SECOND 2 extern time_t TimerTimeout(); static HFONT FAR hfontFixed[4]; static COLORREF FAR acrColours[4][2]; static int cxChar; static int cyChar; static HWND hwndMain = 0; static HWND hwndMDI = 0; static HINSTANCE hInstance = 0; static WNDPROC old_edit_window_proc = 0; static fd_set fdsBusy = { 0 }; static fd_set fdsDCC = { 0 }; static fd_set fdsServer = { 0 }; static fd_set fdsDCCWrite = { 0 }; static char *pchPath = 0; #define WM_SOCKET (WM_USER + 100) #define AT_USCORE 1 #define AT_BOLD 2 #define AT_INVERSE 4 #define AT_STATUS 8 #define AT_FONTFLAGS 3 #define AT_COLOURFLAGS 12 #define AT_COLOURSHIFT 2 typedef struct TermLineStru { char *pchText; char *pchAttribs; } TermLine; char far * far winsock_errors[] = { "no error", /* 10000 */ "(Unknown Error)", /* 10001 */ "(Unknown Error)", /* 10002 */ "(Unknown Error)", /* 10003 */ "call cancelled", /* 10004 */ "(Unknown Error)", /* 10005 */ "(Unknown Error)", /* 10006 */ "(Unknown Error)", /* 10007 */ "(Unknown Error)", /* 10008 */ "bad socket number", /* 10009 */ "(Unknown Error)", /* 10010 */ "(Unknown Error)", /* 10011 */ "(Unknown Error)", /* 10012 */ "permission denied", /* 10013 */ "fault in WinSock call", /* 10014 */ "(Unknown Error)", /* 10015 */ "(Unknown Error)", /* 10016 */ "(Unknown Error)", /* 10017 */ "(Unknown Error)", /* 10018 */ "(Unknown Error)", /* 10019 */ "(Unknown Error)", /* 10020 */ "(Unknown Error)", /* 10021 */ "invalid argument to WinSock call", /* 10022 */ "(Unknown Error)", /* 10023 */ "No more sockets", /* 10024 */ "(Unknown Error)", /* 10025 */ "(Unknown Error)", /* 10026 */ "(Unknown Error)", /* 10027 */ "(Unknown Error)", /* 10028 */ "(Unknown Error)", /* 10029 */ "(Unknown Error)", /* 10030 */ "(Unknown Error)", /* 10031 */ "(Unknown Error)", /* 10032 */ "(Unknown Error)", /* 10033 */ "(Unknown Error)", /* 10034 */ "operation would block", /* 10035 */ "blocking operation in progress", /* 10036 */ "already connected", /* 10037 */ "socket operation on non socket", /* 10038 */ "detstination address required", /* 10039 */ "message too long", /* 10040 */ "protocol wrong type for socket", /* 10041 */ "protocol not available", /* 10042 */ "protocol not supported", /* 10043 */ "socket type not supported", /* 10044 */ "operation not supported on a socket", /* 10045 */ "protocol family not supported", /* 10046 */ "address family not supported", /* 10047 */ "address already in use", /* 10048 */ "can't assign requested address", /* 10049 */ "network is down", /* 10050 */ "network is unreachable", /* 10051 */ "network dropped connection on reset", /* 10052 */ "software caused connection abort", /* 10053 */ "connection reset by peer", /* 10054 */ "no buffer space available", /* 10055 */ "socket is already connected", /* 10056 */ "socket is not connected", /* 10057 */ "can't send after socket shutdown", /* 10058 */ "too many references: can't splice", /* 10059 */ "connection timed out", /* 10060 */ "connection refused", /* 10061 */ "too many levels of symbolic links", /* 10062 */ "file name too long", /* 10063 */ "host is down", /* 10064 */ "no route to host", /* 10065 */ "directory not empty", /* 10066 */ "too many processes", /* 10067 */ "too many users", /* 10068 */ "disk quota exceeded", /* 10069 */ "stale NFS file handle", /* 10070 */ "too many levels of remote in path", /* 10071 */ "(Unknown Error)", /* 10072 */ "(Unknown Error)", /* 10073 */ "(Unknown Error)", /* 10074 */ "(Unknown Error)", /* 10075 */ "(Unknown Error)", /* 10076 */ "(Unknown Error)", /* 10077 */ "(Unknown Error)", /* 10078 */ "(Unknown Error)", /* 10079 */ "(Unknown Error)", /* 10080 */ "(Unknown Error)", /* 10081 */ "(Unknown Error)", /* 10082 */ "(Unknown Error)", /* 10083 */ "(Unknown Error)", /* 10084 */ "(Unknown Error)", /* 10085 */ "(Unknown Error)", /* 10086 */ "(Unknown Error)", /* 10087 */ "(Unknown Error)", /* 10088 */ "(Unknown Error)", /* 10089 */ "(Unknown Error)", /* 10090 */ "Windows Sockets not ready", /* 10091 */ "Windows Sockets version not supported", /* 10092 */ "Windows Sockets not initialised", /* 10093 */ "(Unknown Error)", /* 10094 */ "(Unknown Error)", /* 10095 */ "(Unknown Error)", /* 10096 */ "(Unknown Error)", /* 10097 */ "(Unknown Error)", /* 10098 */ "(Unknown Error)", /* 10099 */ }; static int processable_functions[] = { FALSE, /* BACKSPACE 0 */ FALSE, /* BACKWARD_CHARACTER 1 */ TRUE, /* BACKWARD_HISTORY 2 */ FALSE, /* BACKWARD_WORD 3 */ FALSE, /* BEGINNING_OF_LINE 4 */ TRUE, /* CLEAR_SCREEN 5 */ FALSE, /* COMMAND_COMPLETION 6 */ FALSE, /* DELETE_CHARACTER 7 */ FALSE, /* DELETE_NEXT_WORD 8 */ FALSE, /* DELETE_PREVIOUS_WORD 9 */ FALSE, /* END_OF_LINE 10 */ FALSE, /* ENTER_DIGRAPH 11 */ FALSE, /* ENTER_MENU 12 */ FALSE, /* ERASE_LINE 13 */ FALSE, /* ERASE_TO_BEG_OF_LINE 14 */ FALSE, /* ERASE_TO_END_OF_LINE 15 */ FALSE, /* FORWARD_CHARACTER 16 */ TRUE, /* FORWARD_HISTORY 17 */ FALSE, /* FORWARD_WORD 18 */ FALSE, /* META1_CHARACTER 19 */ FALSE, /* META2_CHARACTER 20 */ FALSE, /* META3_CHARACTER 21 */ FALSE, /* META4_CHARACTER 22 */ TRUE, /* NEXT_WINDOW 23 */ FALSE, /* NOTHING 24 */ TRUE, /* PARSE_COMMAND 25 */ TRUE, /* PREVIOUS_WINDOW 26 */ FALSE, /* QUIT_IRC 27 */ FALSE, /* QUOTE_CHARACTER 28 */ FALSE, /* REFRESH_INPUTLINE 29 */ FALSE, /* REFRESH_SCREEN 30 */ TRUE, /* SCROLL_BACKWARD 31 */ TRUE, /* SCROLL_END 32 */ TRUE, /* SCROLL_FORWARD 33 */ TRUE, /* SCROLL_START 34 */ FALSE, /* SELF_INSERT 35 */ TRUE, /* SEND_LINE 36 */ FALSE, /* STOP_IRC 37 */ TRUE, /* SWAP_LAST_WINDOW 38 */ TRUE, /* SWAP_NEXT_WINDOW 39 */ TRUE, /* SWAP_PREVIOUS_WINDOW 40 */ TRUE, /* SWITCH_CHANNELS 41 */ FALSE, /* TOGGLE_INSERT_MODE 42 */ FALSE, /* TOGGLE_STOP_SCREEN 43 */ FALSE, /* TRANSPOSE_CHARACTERS 44 */ FALSE, /* TYPE_TEXT 45 */ TRUE, /* UNSTOP_ALL_WINDOWS 46 */ FALSE /* YANK_FROM_CUTBUFFER 47 */ }; typedef struct TermStru { int nLines; int nCols; TermLine *ptl; int xPos; int yPos; BOOL bResized; char chAttrib; int iFlags; } Term; #define TF_CTRLDOWN 1 static void set_notifications() { int i; long nTimeout; FD_ZERO(&fdsServer); FD_ZERO(&fdsDCC); FD_ZERO(&fdsDCCWrite); set_server_bits(&fdsServer); set_dcc_bits(&fdsDCC, &fdsDCCWrite); for (i = 0; i < fdsServer.fd_count; i++) { WSAAsyncSelect( fdsServer.fd_array[i], hwndMain, WM_SOCKET, FD_READ | FD_CLOSE); } for (i = 0; i < fdsDCC.fd_count; i++) { WSAAsyncSelect( fdsDCC.fd_array[i], hwndMain, WM_SOCKET, FD_ACCEPT | FD_READ | FD_CLOSE); } nTimeout = TimerTimeout(); if (nTimeout <= 60) SetTimer(hwndMain, TIMER_SECOND, nTimeout * 1000, 0); while (unhold_windows()); } static void process_socket(int s, int iEvent, int iError) { if (FD_ISSET(s, &fdsBusy)) return; FD_SET(s, &fdsBusy); if (FD_ISSET(s, &fdsServer)) { do_server(&fdsServer); } else if (FD_ISSET(s, &fdsDCC)) { dcc_check(&fdsDCC); } FD_CLR(s, &fdsBusy); set_notifications(); } static void get_font(void) { LOGFONT lf; HDC hdc; TEXTMETRIC tm; HFONT hfontOld; int i; hdc = GetDC(GetDesktopWindow()); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cyChar = tm.tmHeight + tm.tmExternalLeading; lf.lfHeight = cyChar; lf.lfWidth = cxChar; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfItalic = 0; lf.lfStrikeOut = 0; lf.lfCharSet = DEFAULT_CHARSET; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE; strcpy(lf.lfFaceName, "System"); for (i = 0; i < 4; i++) { if (i & 2) lf.lfWeight = FW_BOLD; else lf.lfWeight = FW_NORMAL; if (i & 1) lf.lfUnderline = 1; else lf.lfUnderline = 0; hfontFixed[i] = CreateFontIndirect(&lf); } hfontOld = (HFONT) SelectObject(hdc, (HGDIOBJ) hfontFixed[0]); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cyChar = tm.tmHeight + tm.tmExternalLeading; SelectObject(hdc, (HGDIOBJ) hfontOld); ReleaseDC(GetDesktopWindow(), hdc); acrColours[0][0] = GetSysColor(COLOR_WINDOWTEXT); acrColours[0][1] = GetSysColor(COLOR_WINDOW); acrColours[1][0] = acrColours[0][1]; acrColours[1][1] = acrColours[0][0]; acrColours[2][0] = GetSysColor(COLOR_BTNTEXT); acrColours[2][1] = GetSysColor(COLOR_BTNFACE); acrColours[3][0] = GetSysColor(COLOR_CAPTIONTEXT); acrColours[3][1] = acrColours[2][1]; } static Term *new_mswindow(void) { Term *pt; pt = (Term *) new_malloc(sizeof(Term)); pt->nLines = pt->nCols = pt->xPos = pt->yPos = 0; pt->ptl = 0; pt->chAttrib = 0; pt->bResized = FALSE; pt->iFlags = 0; return pt; } static void resize_line(TermLine *ptl, int nOld, int nNew) { char *pchText; char *pchAttribs; int iSmallest; if (nOld == nNew) return; if (nOld < nNew) iSmallest = nOld; else iSmallest = nNew; pchText = (char *) new_malloc(nNew); pchAttribs = (char *) new_malloc(nNew); memcpy(pchText, ptl->pchText, iSmallest); memcpy(pchAttribs, ptl->pchAttribs, iSmallest); memset(pchText + iSmallest, 32, nNew - iSmallest); memset(pchAttribs + iSmallest, 0, nNew - iSmallest); new_free(&ptl->pchText); new_free(&ptl->pchAttribs); ptl->pchAttribs = pchAttribs; ptl->pchText = pchText; } static void resize_window(Term *pt, int x, int y) { TermLine *ptl; int i; int iSmallest; if (y < pt->nLines) iSmallest = y; else iSmallest = pt->nLines; if (y != pt->nLines) { ptl = (TermLine *) new_malloc(sizeof(TermLine) * y); memcpy(ptl, pt->ptl, sizeof(TermLine) * iSmallest); memset(ptl + iSmallest, 0, (y - iSmallest) * sizeof(TermLine)); for (i = iSmallest; i < pt->nLines; i++) { new_free(&pt->ptl[i].pchText); new_free(&pt->ptl[i].pchAttribs); } new_free(&pt->ptl); pt->ptl = ptl; for (i = iSmallest; i < y; i++) resize_line(pt->ptl + i, 0, x); } for (i = 0; i < iSmallest; i++) resize_line(pt->ptl + i, pt->nCols, x); pt->nLines = y; pt->nCols = x; if (pt->xPos >= pt->nCols) pt->xPos = pt->nCols - 1; if (pt->yPos >= pt->nLines) pt->yPos = pt->nLines - 1; } static void char_to_window(Term *pt, char c, HWND hWnd) { RECT rcRedraw; switch(c) { case '\r': pt->xPos = 0; break; case '\n': if (pt->yPos < pt->nLines - 1) pt->yPos++; break; case '\b': if (pt->xPos > 0) pt->xPos--; break; default: pt->ptl[pt->yPos].pchText[pt->xPos] = c; pt->ptl[pt->yPos].pchAttribs[pt->xPos] = pt->chAttrib; rcRedraw.left = pt->xPos * cxChar; rcRedraw.right = rcRedraw.left + cxChar; rcRedraw.top = pt->yPos * cyChar; rcRedraw.bottom = rcRedraw.top + cyChar; InvalidateRect(hWnd, &rcRedraw, TRUE); if (pt->xPos < pt->nCols - 1) pt->xPos++; } } Term *get_window_info(HWND hWnd) { return (Term *) GetWindowLong(hWnd, 0); } void output_to_window(char *pchText, int iLen, HWND hwnd) { Term *pt; pt = get_window_info(hwnd); while (iLen--) char_to_window(pt, *pchText++, hwnd); } static void do_function(HWND hWnd, int iFunc, char *pchArg) { Screen *pscrOld, *pscrNew; char *pchLine; int iLen; pscrOld = current_screen; for (pscrNew = screen_list; pscrNew->hwnd != GetParent(hWnd); pscrNew = pscrNew->next); current_screen = pscrNew; iLen = GetWindowTextLength(hWnd); pchLine = (char *) new_malloc(iLen + 1); GetWindowText(hWnd, pchLine, iLen + 1); if (iFunc == SEND_LINE) { SetWindowText(hWnd, ""); last_input_screen = current_screen; } strmcpy(current_screen->input_buffer + current_screen->buffer_min_pos, pchLine, INPUT_BUFFER_SIZE - current_screen->buffer_min_pos); current_screen->buffer_pos = strlen(current_screen->input_buffer); new_free(&pchLine); key_names[iFunc].func(iFunc, pchArg); set_current_screen(pscrOld); set_notifications(); return 0; } static int do_character(HWND hWnd, UINT wChar, BOOL bAlt) { int iFunc; char *pchArg; if (bAlt) { iFunc = meta1_keys[wChar].index; pchArg = meta1_keys[wChar].stuff; } else { iFunc = keys[wChar].index; pchArg = keys[wChar].stuff; } if (!processable_functions[iFunc]) return 0; else { do_function(hWnd, iFunc, pchArg); return 1; } } LRESULT CALLBACK _export edit_window_proc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { Term *pt; if (wMsg == WM_KEYDOWN) { pt = get_window_info(GetParent(hWnd)); switch(wParam) { case VK_NEXT: do_function(hWnd, SCROLL_FORWARD, 0); return 0; case VK_PRIOR: do_function(hWnd, SCROLL_BACKWARD, 0); return 0; case VK_HOME: if (pt->iFlags & TF_CTRLDOWN) { do_function(hWnd, SCROLL_START, 0); return 0; } break; case VK_END: if (pt->iFlags & TF_CTRLDOWN) { do_function(hWnd, SCROLL_END, 0); return 0; } break; case VK_UP: do_function(hWnd, BACKWARD_HISTORY, 0); return 0; case VK_DOWN: do_function(hWnd, FORWARD_HISTORY, 0); return 0; case VK_CONTROL: pt->iFlags |= TF_CTRLDOWN; break; } } else if (wMsg == WM_KEYUP && wParam == VK_CONTROL) { pt = get_window_info(GetParent(hWnd)); pt->iFlags &= ~TF_CTRLDOWN; } else if (wMsg == WM_CHAR) { if (lParam & 0x20000000 && wParam >= 0 && wParam <= 255) { if (do_character(hWnd, wParam, TRUE)) return 0; } /* Allow binding of control characters other than * backspace, ^C, ^V, and ^X, plus meta1-anything, * which becomes ALT-X */ if (wParam >= 0 && wParam < 32 && wParam != 8 && wParam != 3 && wParam != 24 && wParam != 22) { if (do_character(hWnd, wParam, FALSE)) return 0; } } return CallWindowProc((FARPROC) old_edit_window_proc, hWnd, wMsg, wParam, lParam); } LRESULT CALLBACK _export child_window_proc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { Term *pt; RECT rcClient; int i, j; int xStart, xEnd; PAINTSTRUCT ps; char *pchNull; HWND hwndEdit; HFONT hfontOld; char chAttrib; Screen *pscrOld, *pscrNew; switch(wMsg) { case WM_CREATE: pt = new_mswindow(); SetWindowLong(hWnd, 0, (LONG) pt); GetClientRect(hWnd, &rcClient); hwndEdit = CreateWindow( "EDIT", "", WS_CHILD | WS_HSCROLL | WS_VISIBLE | ES_AUTOHSCROLL, 0, rcClient.bottom - cyChar, rcClient.right, cyChar, hWnd, 0, hInstance, 0); if (!old_edit_window_proc) old_edit_window_proc = (WNDPROC) GetWindowLong(hwndEdit, GWL_WNDPROC); SetWindowLong(hwndEdit, GWL_WNDPROC, (LONG) edit_window_proc); break; case WM_SIZE: if (wParam != SIZE_MINIMIZED) { pt = get_window_info(hWnd); GetClientRect(hWnd, &rcClient); resize_window(pt, rcClient.right / cxChar, rcClient.bottom / cyChar); MoveWindow(GetDlgItem(hWnd, 0), 0, rcClient.bottom - cyChar, rcClient.right, cyChar, TRUE); pscrOld = current_screen; for (pscrNew = screen_list; pscrNew && pscrNew->hwnd != hWnd; pscrNew = pscrNew->next); if (pscrNew) { current_screen = pscrNew; pt->bResized = TRUE; refresh_screen(); } if (pscrOld) set_current_screen(pscrOld); else current_screen = 0; } break; case WM_MDIACTIVATE: SetFocus(GetDlgItem(hWnd, 0)); break; case WM_PAINT: pt = get_window_info(hWnd); BeginPaint(hWnd, &ps); hfontOld = (HFONT) SelectObject(ps.hdc, (HGDIOBJ) hfontFixed[0]); for (i = 0; i < pt->nLines; i++) { xStart = 0; while (xStart < pt->nCols && pt->ptl[i].pchText[xStart]) { xEnd = xStart; chAttrib = pt->ptl[i].pchAttribs[xStart]; while (++xEnd < pt->nCols && pt->ptl[i].pchText[xEnd] && pt->ptl[i].pchAttribs[xEnd] == chAttrib); SelectObject(ps.hdc, (HGDIOBJ) hfontFixed[chAttrib & AT_FONTFLAGS]); SetTextColor(ps.hdc, acrColours[(chAttrib & AT_COLOURFLAGS) >> AT_COLOURSHIFT][0]); SetBkColor(ps.hdc, acrColours[(chAttrib & AT_COLOURFLAGS) >> AT_COLOURSHIFT][1]); TextOut(ps.hdc, cxChar * xStart, cyChar * i, pt->ptl[i].pchText + xStart, xEnd - xStart); xStart = xEnd; } } SelectObject(ps.hdc, (HGDIOBJ) hfontOld); EndPaint(hWnd, &ps); return 0; case WM_CLOSE: pscrOld = current_screen; for (pscrNew = screen_list; pscrNew && pscrNew->hwnd != hWnd; pscrNew = pscrNew->next); if (pscrNew) kill_screen(pscrNew); if (pscrOld) set_current_screen(pscrOld); else current_screen = 0; break; } return DefMDIChildProc(hWnd, wMsg, wParam, lParam); } LRESULT CALLBACK _export main_window_proc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { LRESULT iValue; switch(wMsg) { case WM_SOCKET: process_socket(wParam, WSAGETSELECTEVENT(lParam), WSAGETSELECTERROR(lParam)); return 0; case WM_SETFOCUS: iValue = SendMessage(hwndMDI, WM_MDIGETACTIVE, 0, 0L); SetFocus(GetDlgItem((HWND) LOWORD(iValue), 0)); break; case WM_CLOSE: e_quit("QUIT", "Closed main window"); break; case WM_TIMER: switch(wParam) { case TIMER_MINUTE: if (get_int_var(CLOCK_VAR)) { status_update(1); cursor_to_input(); } do_notify(); break; case TIMER_SECOND: KillTimer(hWnd, TIMER_SECOND); ExecuteTimers(); break; } set_notifications(); break; case WM_COMMAND: switch(wParam) { case 101: e_quit("QUIT", "Selected exit option on menu"); break; case 201: SendMessage(hwndMDI, WM_MDITILE, MDITILE_VERTICAL, 0); break; case 202: SendMessage(hwndMDI, WM_MDITILE, MDITILE_HORIZONTAL, 0); break; case 203: SendMessage(hwndMDI, WM_MDICASCADE, 0, 0); break; case 204: SendMessage(hwndMDI, WM_MDIICONARRANGE, 0, 0); break; } break; } if (hwndMDI) return DefFrameProc(hWnd, hwndMDI, wMsg, wParam, lParam); else return DefWindowProc(hWnd, wMsg, wParam, lParam); } int PASCAL WinMain(HANDLE hInstance_, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; RECT rcClient; MSG msg; CLIENTCREATESTRUCT ccs; WSADATA wsad; char *argv[3]; MODULEENTRY me; TASKENTRY te; memset(&te, 0, sizeof(te)); te.dwSize = sizeof(te); TaskFindHandle(&te, GetCurrentTask()); memset(&me, 0, sizeof(me)); me.dwSize = sizeof(me); ModuleFindHandle(&me, te.hModule); *strrchr(me.szExePath, '\\') = 0; malloc_strcpy(&pchPath, me.szExePath); hInstance = hInstance_; switch(WSAStartup(0x0101, &wsad)) { case 0: if (wsad.wVersion != 0x0101) { MessageBox(0, "Your Windows Sockets version is too new", 0, MB_OK); exit(1); } break; case WSAVERNOTSUPPORTED: MessageBox(0, "Windows Sockets 1.1 is required", 0, MB_OK); exit(1); break; case WSASYSNOTREADY: MessageBox(0, "Windows Sockets is not ready", 0, MB_OK); exit(1); break; default: MessageBox(0, "Could not initialise Windows Sockets", 0, MB_OK); exit(1); break; } get_font(); memset(&wc, 0, sizeof(wc)); wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, "IRC_ICO"); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = COLOR_WINDOW + 1; wc.lpszClassName = "IRCII Main Window"; wc.lpszMenuName = "MAIN_MNU"; wc.lpfnWndProc = main_window_proc; RegisterClass(&wc); wc.lpfnWndProc = child_window_proc; wc.lpszClassName = "IRCII Child Window"; wc.lpszMenuName = 0; wc.cbWndExtra = sizeof(void *); RegisterClass(&wc); hwndMain = CreateWindow( "IRCII Main Window", "IRC II for Windows", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, nCmdShow, CW_USEDEFAULT, 0, 0, 0, hInstance, 0); GetClientRect(hwndMain, &rcClient); ccs.hWindowMenu = GetSubMenu(GetMenu(hwndMain), 1); ccs.idFirstChild = 1000; hwndMDI = CreateWindow( "MDICLIENT", "IRC II MDI Window", WS_CLIPCHILDREN | WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE, 0, 0, rcClient.right, rcClient.bottom, hwndMain, 0, hInstance, &ccs); build_status(); argv[0] = "ircii"; argv[1] = lpCmdLine; argv[2] = 0; old_main(2, argv); current_screen = screen_list; set_notifications(); SetTimer(hwndMain, TIMER_MINUTE, 60000, 0); while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } DeleteObject((HGDIOBJ) hfontFixed); WSACleanup(); } int getpid(void) { return (int) hInstance; } int getppid(void) { return 1; } void execcmd(void) { yell("EXEC is not available under Windows"); } void win_create_window(Screen *pscr) { MDICREATESTRUCT mdic; char achNumber[40]; static int nWindow = 0; mdic.szClass = "IRCII Child Window"; sprintf(achNumber, "Window %d", ++nWindow); mdic.szTitle = achNumber; mdic.hOwner = hInstance; mdic.x = CW_USEDEFAULT; mdic.y = CW_USEDEFAULT; mdic.cx = CW_USEDEFAULT; mdic.cy = CW_USEDEFAULT; mdic.style = 0; mdic.lParam = 0; pscr->hwnd = (HWND) SendMessage(hwndMDI, WM_MDICREATE, 0, (LPARAM) &mdic); } void term_beep(void) { MessageBeep(0); } void term_move_cursor(int x, int y) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->xPos = x; pt->yPos = y; if (pt->xPos >= pt->nCols) pt->xPos = pt->nCols - 1; if (pt->yPos >= pt->nLines) pt->yPos = pt->nLines - 1; } void term_cr(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->xPos = 0; } void term_newline(void) { Term *pt; pt = get_window_info(current_screen->hwnd); if (pt->yPos < pt->nLines - 1) pt->yPos++; } int term_scroll(int yStart, int yEnd, int yScroll) { Term *pt; TermLine *ptl; BOOL bNegative = FALSE; int i; RECT rcScroll; if (yScroll == 0) return 1; if (yScroll < 0) { bNegative = TRUE; yScroll = -yScroll; } pt = get_window_info(current_screen->hwnd); if (yStart < 0) yStart = 0; if (yEnd >= pt->nLines) yEnd = pt->nLines - 1; if (yScroll >= yEnd - yStart + 1) yScroll = yEnd - yStart + 1; ptl = (TermLine *) new_malloc(sizeof(TermLine) * yScroll); if (bNegative) { memcpy(ptl, pt->ptl + yEnd + 1 - yScroll, sizeof(TermLine) * yScroll); memmove(pt->ptl + yStart + yScroll, pt->ptl + yStart, (yEnd - yStart + 1 - yScroll) * sizeof(TermLine)); memcpy(pt->ptl + yStart, ptl, sizeof(TermLine) * yScroll); for (i = yStart; i < yStart + yScroll; i++) { memset(pt->ptl[i].pchText, 32, pt->nCols); memset(pt->ptl[i].pchAttribs, 0, pt->nCols); } } else { memcpy(ptl, pt->ptl + yStart, sizeof(TermLine) * yScroll); memmove(pt->ptl + yStart, pt->ptl + yStart + yScroll, (yEnd - yStart + 1 - yScroll) * sizeof(TermLine)); memcpy(pt->ptl + yEnd + 1 - yScroll, ptl, sizeof(TermLine) * yScroll); for (i = yEnd + 1 - yScroll; i <= yEnd; i++) { memset(pt->ptl[i].pchText, 32, pt->nCols); memset(pt->ptl[i].pchAttribs, 0, pt->nCols); } } new_free(&ptl); GetClientRect(current_screen->hwnd, &rcScroll); rcScroll.top = cyChar * yStart; rcScroll.bottom = cyChar * (yEnd + 1); ScrollWindow(current_screen->hwnd, 0, cyChar * yScroll * (bNegative ? 1 : -1), &rcScroll, &rcScroll); return 1; } #define AT_BOLD 2 #define AT_INVERSE 4 #define AT_STATUS 8 void term_underline_on(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib |= AT_USCORE; } void term_underline_off(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib &= ~AT_USCORE; } void term_standout_on(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib |= AT_INVERSE; } void term_standout_off(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib &= ~AT_INVERSE; } void term_bold_on(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib |= AT_BOLD; } void term_bold_off(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib &= ~AT_BOLD; } void term_status_on(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib |= AT_STATUS; } void term_status_off(void) { Term *pt; pt = get_window_info(current_screen->hwnd); pt->chAttrib &= ~AT_STATUS; } int term_clear_screen(void) { int i; Term *pt; if (!current_screen) return 0; pt = get_window_info(current_screen->hwnd); for (i = 0; i < pt->nLines; i++) { memset(pt->ptl[i].pchText, 32, pt->nCols); memset(pt->ptl[i].pchAttribs, pt->chAttrib, pt->nCols); } InvalidateRect(current_screen->hwnd, 0, TRUE); return 0; } int term_clear_to_eol(void) { Term *pt; RECT rcRedraw; pt = get_window_info(current_screen->hwnd); memset(pt->ptl[pt->yPos].pchText + pt->xPos, 32, pt->nCols - pt->xPos); memset(pt->ptl[pt->yPos].pchAttribs + pt->xPos, pt->chAttrib, pt->nCols - pt->xPos); rcRedraw.top = pt->yPos * cyChar; rcRedraw.bottom = rcRedraw.top + cyChar; rcRedraw.left = pt->xPos * cxChar; rcRedraw.right = pt->nCols * cxChar; InvalidateRect(current_screen->hwnd, &rcRedraw, TRUE); return 0; } int term_space_erase(int nChars) { Term *pt; RECT rcRedraw; pt = get_window_info(current_screen->hwnd); if (nChars > pt->nCols - pt->xPos) nChars = pt->nCols - pt->xPos; memset(pt->ptl[pt->yPos].pchText + pt->xPos, 32, nChars); memset(pt->ptl[pt->yPos].pchAttribs + pt->xPos, pt->chAttrib, nChars); rcRedraw.top = pt->yPos * cyChar; rcRedraw.bottom = rcRedraw.top + cyChar; rcRedraw.left = pt->xPos * cxChar; rcRedraw.right = pt->nCols * cxChar; InvalidateRect(current_screen->hwnd, &rcRedraw, TRUE); return 0; } int term_delete(void) { Term *pt; RECT rcScroll; pt = get_window_info(current_screen->hwnd); memmove(pt->ptl[pt->yPos].pchText + pt->xPos, pt->ptl[pt->yPos].pchText + pt->xPos + 1, pt->nCols = pt->xPos + 1); memmove(pt->ptl[pt->yPos].pchAttribs + pt->xPos, pt->ptl[pt->yPos].pchAttribs + pt->xPos + 1, pt->nCols = pt->xPos + 1); pt->ptl[pt->yPos].pchText[pt->nCols - 1] = ' '; pt->ptl[pt->yPos].pchAttribs[pt->nCols - 1] = pt->chAttrib; rcScroll.top = pt->yPos * cyChar; rcScroll.bottom = rcScroll.top + cyChar; rcScroll.left = pt->xPos * cxChar; rcScroll.right = pt->nCols * cxChar; ScrollWindow(current_screen->hwnd, -cxChar, cyChar, &rcScroll, &rcScroll); return 0; } int term_get_columns(void) { Term *pt; RECT rcRedraw; if (!current_screen) return 80; pt = get_window_info(current_screen->hwnd); return pt->nCols; } int term_get_rows(void) { Term *pt; RECT rcRedraw; if (!current_screen) return 80; pt = get_window_info(current_screen->hwnd); return pt->nLines; } int term_flush(void) { UpdateWindow(current_screen->hwnd); } int term_resize(void) { Term *pt; RECT rcRedraw; BOOL bResized; if (!current_screen) return 0; pt = get_window_info(current_screen->hwnd); bResized = pt->bResized; pt->bResized = 0; return bResized; } void set_input(str) char *str; { Term *pt; int iLen; pt = get_window_info(current_screen->hwnd); SetWindowText(GetDlgItem(current_screen->hwnd, 0), str); iLen = strlen(str); SendMessage(GetDlgItem(current_screen->hwnd, 0), EM_SETSEL, 0, MAKELPARAM(iLen, iLen)); } char * get_input() { return (&(current_screen->input_buffer[current_screen->buffer_min_pos])); } char * get_path(int iVal) { static char FAR buffer[BIG_BUFFER_SIZE]; strcpy(buffer, pchPath); switch(iVal) { case 0: /* Irc Lib (with trailing slash) */ strcat(buffer, "/LIB/"); break; case 1: /* Help Path */ strcat(buffer, "/HELP"); break; case 2: /* Translation Path */ strcat(buffer, "/TRANSLAT"); break; case 3: /* Load Path */ strcat(buffer, "/SCRIPTS"); break; case 4: /* IRC directory */ break; } return buffer; }