char *cknwin = "Win32 GUI Support 8.0.029, 10 March 2004"; /* C K N W I N -- Kermit GUI Windows support for Win32 systems */ /* Author: Jeffrey Altman (jaltman@secure-endpoints.com) Secure Endpoints Inc., New York City Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New York. */ #include #include #include #include "ckcdeb.h" #include "ckcker.h" #include "ckcasc.h" #include "cknwin.h" #include "ckowin.h" #include "ckntap.h" #include "ckocon.h" #include "ckuusr.h" #include "ckokey.h" #include "ckokvb.h" #include "ckosyn.h" #include "richedit.h" /* Global variable */ HINSTANCE hInst = 0 ; extern HINSTANCE hInstance ; HWND hwndGUI = NULL ; HWND hwndConsole = NULL ; extern HWND hwndDialer ; extern LONG KermitDialerID ; extern int DeleteStartupFile; extern char cmdfil[]; #ifdef KUI #include "kui/ikcmd.h" #include "kui/ikui.h" extern struct _kui_init kui_init; #endif /* KUI */ /* Function prototypes */ #ifdef CK_WIN int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int); #endif InitApplication(HINSTANCE); InitInstance(HINSTANCE, int); LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); /* Application entry point */ #ifdef COMMENT int WINAPI WinMain(hinstance, hPrevInstance, lpCmdLine, nCmdShow) HINSTANCE hinstance; HINSTANCE hPrevInstance; LPSTR lpCmdLine; int nCmdShow; #endif #ifndef CK_WIN HANDLE WindowThread = INVALID_HANDLE_VALUE; DWORD WindowThreadId = -1 ; void ckWindowThread( void * hInstance ) { HINSTANCE hinstance = (HINSTANCE) hInstance ; int nCmdShow = SW_SHOW ; MSG msg; extern int SysInited; setint(); if (!InitApplication(hinstance)) { debug( F100, "ckWindowThread InitApplication failed","",0 ); WindowThreadId = 0; _endthread(); } if (!InitInstance(hinstance, nCmdShow)) { debug( F100, "ckWindowThread InitInstance failed","",0 ); WindowThreadId = 0; _endthread(); } debug( F100, "ckWindowThread Init successful","",0 ); WindowThreadId = GetCurrentThreadId(); while (GetMessage(&msg, (HWND) NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } #ifndef NOKVERBS if ( SysInited ) { debug(F110,"ckWindowThread","dokverb QUIT",0); dokverb( VTERM, K_QUIT ); } else #endif /* NOKVERBS */ debug(F110,"ckWindowThread","quitting",0); } int WindowThreadInit( void * hInstance ) { WindowThread = (HANDLE) _beginthread( ckWindowThread, 65535, hInstance ) ; do { msleep(50); } while ( WindowThreadId == -1 ); if ( WindowThreadId == 0 ) return FALSE; #ifdef COMMENT if (!AttachThreadInput( GetCurrentThreadId(), WindowThreadId, TRUE )) printf("AttachThreadInput error = %d\n",GetLastError()); #endif /* COMMENT */ return TRUE ; } void WindowThreadClose( void ) { debug(F100,"Window Thread Close","",0); PostMessage(hwndGUI, WM_QUIT, 0, 0); msleep(50); } #else HANDLE MainThread = NULL ; #ifdef COMMENT int WindowThreadInit( void ) { return TRUE ; } #else /* COMMENT */ HANDLE WindowThread = INVALID_HANDLE_VALUE; DWORD WindowThreadId = -1 ; void ckWindowThread( void * hInstance ) { HINSTANCE hinstance = (HINSTANCE) hInstance ; int nCmdShow = SW_HIDE ; MSG msg; WindowThreadId = GetCurrentThreadId(); if (!InitApplication(hinstance)) { debug( F100, "ckWindowThread InitApplication failed","",0 ); _endthread(); } if (!InitInstance(hinstance, nCmdShow)) { debug( F100, "ckWindowThread InitInstance failed","",0 ); _endthread(); } debug( F100, "ckWindowThread Init successful","",0 ); while (GetMessage(&msg, (HWND) NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } int WindowThreadInit( void * hInstance ) { WindowThread = (HANDLE) _beginthread( ckWindowThread, 65535, hInstance ) ; while ( WindowThreadId == -1 ) msleep(50); if (!AttachThreadInput( GetCurrentThreadId(), WindowThreadId, TRUE )) printf("AttachThreadInput error = %d\n",GetLastError()); return TRUE ; } #endif /* COMMENT */ extern void Main( int, char ** ) ; void ckMainThread( void * param ) { LPTSTR CmdLine = GetCommandLine() ; HANDLE hOut, hIn ; char ** argv; int argc = 0 ; int i = 0, quote = 0 ; char * p = CmdLine ; debug(F111,"GetCommandLine()",CmdLine,strlen(CmdLine)); hInstance = (HINSTANCE) param ; while( *p ) { if ( *p == '"' && !quote ) { quote++; } else if ( quote && *p == '"' ) { quote = 0; while ( *(p+1) == ' ' ) p++ ; if ( *(p+1) != '\0' ) argc++; } else if ( !quote && *p == ' ' && *(p+1) != '\0' ) { argc++ ; while ( *(p+1) == ' ' ) p++ ; } p++; } argc++ ; argv = malloc( (argc+1) * sizeof(char *) ) ; debug(F111,"ckMainThread","argc",argc); if ( argv == NULL ) { fprintf(stderr,"Out of memory\n"); exit(1); } else { argv[argc] = "" ; p = CmdLine ; for ( i = 0; i < argc ; i++ ) { if ( *p == '"' ) { p++; argv[i] = p ; while (*p && (*p != '"')) p++; if (*p) *p++ = '\0'; while (*p && (*p == ' ')) p++; } else { argv[i] = p ; while ( *p && (*p != ' ') ) p++ ; if (*p) *p++ = '\0'; while (*p && (*p == ' ')) p++; } debug(F111,"ckMainThread argv",argv[i],i); } } #ifndef KUI if ( AllocConsole() ) { hOut = CreateFile( "CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0) ; hIn = CreateFile( "CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0) ; SetStdHandle( STD_INPUT_HANDLE, hIn ) ; SetStdHandle( STD_OUTPUT_HANDLE, hOut ) ; SetStdHandle( STD_ERROR_HANDLE, hOut ); } #endif /* KUI */ Main( argc, argv ) ; } HANDLE MainThreadInit( HINSTANCE hInst ) { MainThread = (HANDLE) _beginthread( ckMainThread, 65535, hInst ) ; return(MainThread); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { #ifdef KUI extern int deblog ; kui_init.nCmdShow = nCmdShow; ckMainThread( hInstance ) ; return 0; #else /* KUI */ MSG msg; HINSTANCE hModule = GetModuleHandle(NULL); if (!InitApplication(hInstance)) { debug( F100, "InitApplication failed","",0 ); return 0; } if (!InitInstance(hInstance, nCmdShow)) { debug( F100, "InitInstance failed","",0 ); return 0; } MainThreadInit(hInstance) ; while (GetMessage(&msg, (HWND) NULL, 0, 0)) { printf("GetMessage\n"); TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam ; #endif /* KUI */ } #endif BOOL InitApplication(hinstance) HINSTANCE hinstance; { WNDCLASSEX wcx; /* * Fill in the window class structure with parameters * that describe the main window. */ wcx.cbSize = sizeof(wcx); /* size of structure */ wcx.style = CS_HREDRAW | CS_VREDRAW; /* redraw if size changes */ wcx.lpfnWndProc = MainWndProc; /* points to window proc. */ wcx.cbClsExtra = 0; /* no extra class memory */ wcx.cbWndExtra = 0; /* no extra window memory */ wcx.hInstance = hinstance; /* handle of instance */ wcx.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(1)); /* kermit 95 icon */ wcx.hCursor = LoadCursor(NULL, IDC_ARROW); /* predefined arrow */ wcx.hbrBackground = GetStockObject( WHITE_BRUSH); /* white background brush */ wcx.lpszMenuName = "CkMainMenu"; /* name of menu resource */ wcx.lpszClassName = "CkMainWClass"; /* name of window class */ wcx.hIconSm = LoadImage(hinstance, /* small class icon */ MAKEINTRESOURCE(5), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); /* Register the window class. */ return RegisterClassEx(&wcx); } BOOL InitInstance(hinstance, nCmdShow) HINSTANCE hinstance; int nCmdShow; { /* Save the application-instance handle. */ hInst = hinstance; /* Create the main window. */ #ifndef CK_WIN hwndGUI = CreateWindow( "CkMainWClass", /* name of window class */ "Kermit 95", /* title-bar string */ WS_CHILD, /* top-level window */ CW_USEDEFAULT, /* default horizontal position */ CW_USEDEFAULT, /* default vertical position */ CW_USEDEFAULT, /* default width */ CW_USEDEFAULT, /* default height */ (HWND) hwndConsole, /* console window */ (HMENU) 1, /* use class menu */ hinstance, /* handle of app. instance */ (LPVOID) NULL); /* no window-creation data */ #else hwndGUI = CreateWindow( "CkMainWClass", /* name of window class */ "Kermit 95", /* title-bar string */ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, /* default horizontal position */ CW_USEDEFAULT, /* default vertical position */ CW_USEDEFAULT, /* default width */ CW_USEDEFAULT, /* default height */ (HWND) NULL, (HMENU) NULL, /* use class menu */ hinstance, /* handle of app. instance */ (LPVOID) NULL); /* no window-creation data */ #endif if (!hwndGUI) return FALSE; ShowWindow( hwndGUI, SW_HIDE ) ; /* Let the dialer know */ if ( StartedFromDialer ) DialerSend( OPT_KERMIT_HWND, (LONG) hwndGUI ) ; /* * Show the window and send a WM_PAINT message to the window * procedure. */ ShowWindow(hwndGUI, nCmdShow); UpdateWindow(hwndGUI); return TRUE; } LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { LRESULT result = 0 ; extern unsigned long startflags; switch ( msg ) { case WM_QUERYENDSESSION: debug(F111,"MainWndProc","WM_QUERYENDSESSION",msg); result = TRUE; if ( lparam & ENDSESSION_LOGOFF ) { debug(F100,"ENDSESSION_LOGOFF","",0); if ( startflags & 128 ) { debug(F100,"startflags & 128","",0); result = FALSE; } } break; case WM_ENDSESSION: debug(F111,"MainWndProc","WM_QUERYENDSESSION",msg); if ( wparam && (lparam & ENDSESSION_LOGOFF) ) { debug(F100,"ENDSESSION_LOGOFF","",0); if ( startflags & 128 ) { debug(F100,"startflags & 128","",0); result = TRUE; } } break; #ifdef CK_TAPI case OPT_TAPI_INIT: debug(F110,"K95 WndProc","OPT_TAPI_INIT",0); wintapiinit(); result = TRUE; break; case OPT_TAPI_SHUTDOWN: debug(F110,"K95 WndProc","OPT_TAPI_SHUTDOWN",0); wintapishutdown(); result = TRUE; break; #endif /* CK_TAPI */ case OPT_KERMIT_HANGUP: debug(F110,"K95 WndProc","OPT_KERMIT_HANGUP",0); #ifndef NOLOCAL if ( IsConnectMode() ) SetConnectMode( FALSE, CSX_USERDISC ) ; #endif /* NOLOCAL */ putkeystr( VCMD, "hangup\rexit\ryes\r" ) ; DialerSend( OPT_KERMIT_HANGUP, 0 ) ; result = TRUE; break; #ifndef NOLOCAL case OPT_DIALER_EXIT: debug(F110,"K95 WndProc","OPT_DIALER_EXIT",0); StartedFromDialer = 0; hwndDialer = 0; KermitDialerID = 0; result = TRUE; break; case OPT_DIALER_HWND: debug(F110,"K95 WndProc","OPT_DIALER_HWND",0); StartedFromDialer = 1; hwndDialer = (HWND)lparam; KermitDialerID = wparam; result = TRUE; break; case OPT_DIALER_CONNECT: { char buf[300], file[256]; debug(F110,"K95 WndProc","OPT_DIALER_CONNECT",0); if ( GlobalGetAtomName((ATOM)lparam,file,sizeof(file)) ) { debug(F110,"Take File",file,0); ckmakmsg(buf,300,"take ",file,"\r",NULL); GlobalDeleteAtom((ATOM)lparam); putkeystr( VCMD, buf ); if ( IsConnectMode() ) SetConnectMode(0,CSX_ESCAPE); if ( DeleteStartupFile ) { zdelet(cmdfil); ckstrncpy(cmdfil,file,CKMAXPATH+1); } else { ckstrncpy(cmdfil,file,CKMAXPATH+1); DeleteStartupFile = 1; } DialerSend( OPT_KERMIT_HWND, (LONG) hwnd ) ; } result = TRUE; break; } #endif /* NOLOCAL */ default: debug(F111,"K95 WndProc","unknown message",msg); debug(F111,"K95 WndProc","wparam",wparam); debug(F111,"K95 WndProc","lparam",lparam); result = DefWindowProc( hwnd, msg, wparam, lparam ); } return result ; } void StartDialer(void) { extern int cmdlvl; #ifdef DCMDBUF extern struct cmdptr *cmdstk; #else extern struct cmdptr cmdstk[]; #endif /* DCMDBUF */ extern char exedir[CKMAXPATH]; extern int nopush; HWND _hwndDialer = 0; int reuse; if ( nopush ) return; #ifndef NOSPL reuse = (cmdlvl == 0) && (ttchk() < 0); #else reuse = (tlevel == -1) && (ttchk() < 0); #endif /* NOSPL */ if ( StartedFromDialer ) { if ( reuse ) { DialerSend(OPT_KERMIT_HWND2, (unsigned long)hwndGUI); DialerSend(OPT_KERMIT_PID, GetCurrentProcessId()); } ShowWindowAsync(hwndDialer,SW_SHOWNORMAL); SetForegroundWindow(hwndDialer); } else if (_hwndDialer = FindWindow(NULL, "Kermit-95 Dialer")) { StartedFromDialer = 1; hwndDialer = _hwndDialer; KermitDialerID = 0; DialerSend(OPT_KERMIT_HWND, (unsigned long)hwndGUI); if ( reuse ) { DialerSend(OPT_KERMIT_HWND2, (unsigned long)hwndGUI); DialerSend(OPT_KERMIT_PID, GetCurrentProcessId()); } ShowWindowAsync(hwndDialer,SW_SHOWNORMAL); SetForegroundWindow(hwndDialer); StartedFromDialer = 0; } else { static char buf[512] = "start ", *p, *q; for ( p = exedir, q = buf + 6; *p; p++, q++ ) { if ( *p == '/' ) { *q = '\\'; } else *q = *p; if ( *q == '\\' ) { q++; *q = '\\'; } } for ( p = "k95dial.exe"; *p ; p++, q++ ) *q = *p; if ( reuse ) { for ( p = " -k "; *p ; p++, q++ ) *q = *p; for ( p = ckultoa((LONG) hwndGUI); *p ; p++, q++ ) *q = *p; *q++ = ' '; for ( p = ckultoa((LONG) GetCurrentProcessId()); *p ; p++, q++ ) *q = *p; } *q = '\0'; _zshcmd(buf,0); } } HWND GetConsoleHwnd( void ) { #ifdef KUI return getHwndKUI(); #else /* KUI */ HWND hwndFound = NULL ; char NewWindowTitle[1024] ; char OldWindowTitle[1024] ; int i = 0 ; GetConsoleTitle( OldWindowTitle, 1024 ) ; for ( i=0 ; i < 20 ; i++ ) { wsprintf( NewWindowTitle, "%d/%d", GetTickCount(), GetCurrentProcessId()); SetConsoleTitle(NewWindowTitle); Sleep(50); hwndFound = FindWindow( NULL, NewWindowTitle ) ; if ( hwndFound ) break; } debug(F111,"GetConsoleHwnd","Hwnd",hwndFound) ; SetConsoleTitle( OldWindowTitle ) ; return (hwndFound); #endif /* KUI */ } #ifdef KUI static LPWORD lpwAlign( LPWORD lpIn ) { ULONG ul; ul = (ULONG) lpIn; ul += 3; ul >>=2; ul <<=2; return (LPWORD) ul;; } static char * sid_buf = NULL; static int sid_len = 0; static int sid_timeout = 0; static UINT sid_timer = 0; #define ID_TEXT 150 #define ID_SID_TEXT 200 #define ID_SID_TIMER (WM_USER+300) static BOOL CALLBACK SingleInputDialogProc( HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch ( message ) { case WM_INITDIALOG: if ( sid_timeout ) { sid_timer = SetTimer( hwndDlg, ID_SID_TIMER, sid_timeout * 1000, NULL); } if ( GetDlgCtrlID((HWND) wParam) != ID_SID_TEXT ) { SetFocus(GetDlgItem( hwndDlg, ID_SID_TEXT)); return FALSE; } return TRUE; case WM_COMMAND: switch ( LOWORD(wParam) ) { case IDOK: if ( !GetDlgItemText(hwndDlg, ID_SID_TEXT, sid_buf, sid_len) ) *sid_buf = '\0'; /* fallthrough */ case IDCANCEL: if ( sid_timeout ) KillTimer(hwndDlg,sid_timer); EndDialog(hwndDlg, LOWORD(wParam)); return TRUE; } break; case WM_TIMER: if ( sid_timeout ) KillTimer(hwndDlg,sid_timer); EndDialog(hwndDlg, 0); return TRUE; } return FALSE; } /* * dialog widths are measured in 1/4 character widths * dialog height are measured in 1/8 character heights */ static LRESULT SingleInputDialog( HINSTANCE hinst, HWND hwndOwner, char * ptext[], int numlines, int width, char * prompt, int echo, char * dflt) { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar, i; char * p; hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096); if (!hgbl) return -1; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_CENTER | DS_SETFOREGROUND | DS_3DLOOK | DS_SHELLFONT | DS_NOFAILCREATE; lpdt->cdit = numlines + 4; // number of controls lpdt->x = 10; lpdt->y = 10; lpdt->cx = 20 + width * 4; lpdt->cy = 20 + (numlines + 4) * 14; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, prompt, -1, lpwsz, 128); lpw += nchar; *lpw++ = 8; // font size (points) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg", -1, lpwsz, 128); lpw += nchar; //----------------------- // Define an OK button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)/4 - 20; lpdit->y = 10 + (numlines + 3) * 14; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDOK; // OK button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data //----------------------- // Define an Cancel button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)*3/4 - 20; lpdit->y = 10 + (numlines + 3) * 14; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDCANCEL; // CANCEL button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data /* Add controls for preface data */ for ( i=0; istyle = WS_CHILD | WS_VISIBLE | SS_LEFT; lpdit->dwExtendedStyle = 0; lpdit->x = 10; lpdit->y = 10 + i * 14; lpdit->cx = strlen(ptext[i]) * 4 + 10; lpdit->cy = 14; lpdit->id = ID_TEXT + i; // text identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i], -1, lpwsz, 2*width); lpw += nchar; *lpw++ = 0; // no creation data } /* Prompt */ /*----------------------- * Define a static text control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; lpdit->dwExtendedStyle = 0; lpdit->x = 10; lpdit->y = 10 + (numlines + 1) * 14; lpdit->cx = strlen(prompt) * 4; lpdit->cy = 14; lpdit->id = ID_TEXT + (numlines); // text identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, prompt, -1, lpwsz, 128); lpw += nchar; *lpw++ = 0; // no creation data /*----------------------- * Define an edit control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (echo == 1 ? 0L : ES_PASSWORD); lpdit->dwExtendedStyle = 0; lpdit->x = 10 + (strlen(prompt) + 1) * 4; lpdit->y = 10 + (numlines + 1) * 14; lpdit->cx = (width - (strlen(prompt) + 1)) * 4; lpdit->cy = 14; lpdit->id = ID_SID_TEXT; // identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0081; // edit class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, dflt ? dflt : "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 0; // no creation data GlobalUnlock(hgbl); ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) SingleInputDialogProc); GlobalFree(hgbl); switch ( ret ) { case 0: /* Timeout */ return -1; case IDOK: return 1; case IDCANCEL: return 0; default: { char buf[256]; ckmakmsg(buf,256,"DialogBoxIndirect() failed ",ckitoa(GetLastError()), NULL, NULL); MessageBox(hwndOwner, buf, "GetLastError()", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); return -1; } } } int gui_txt_dialog(char * preface, char * prompt, int echo, char * buf, int buflen, char * dflt, int timeout) { int maxwidth = 0; int numlines = 0; char * plines[16], *p = preface ? preface : ""; int i; if ( !buf || buflen <= 0 || buflen < (dflt ? strlen(dflt) : 0) ) return(-1); sid_buf = buf; sid_len = buflen; sid_timeout = timeout; for ( i=0; i<16; i++ ) plines[i] = NULL; while (*p && numlines < 16) { plines[numlines++] = p; for ( ;*p && *p != '\r' && *p != '\n'; p++ ); if ( *p == '\r' && *(p+1) == '\n' ) { *p++ = '\0'; p++; } else if ( *p == '\n' ) { *p++ = '\0'; } if ( strlen(plines[numlines-1]) > maxwidth ) maxwidth = strlen(plines[numlines-1]); } i = strlen(prompt) + 1 + (buflen > 40 ? 40 : buflen); if ( maxwidth < i ) maxwidth = i; return(SingleInputDialog(hInstance, hwndConsole, plines, numlines, maxwidth, prompt, echo, dflt)); } static int mid_cnt = 0; static struct txtbox * mid_tb = NULL; #define ID_MID_TEXT 300 static BOOL CALLBACK MultiInputDialogProc( HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { int i; switch ( message ) { case WM_INITDIALOG: if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT ) { SetFocus(GetDlgItem( hwndDlg, ID_MID_TEXT)); return FALSE; } return TRUE; case WM_COMMAND: switch ( LOWORD(wParam) ) { case IDOK: for ( i=0; i < mid_cnt ; i++ ) { if ( !GetDlgItemText(hwndDlg, ID_MID_TEXT+i, mid_tb[i].t_buf, mid_tb[i].t_len) ) *mid_tb[i].t_buf = '\0'; } /* fallthrough */ case IDCANCEL: ShowWindowAsync(hwndConsole,SW_SHOWNORMAL); SetForegroundWindow(hwndConsole); EndDialog(hwndDlg, LOWORD(wParam)); return TRUE; } } return FALSE; } /* * dialog widths are measured in 1/4 character widths * dialog height are measured in 1/8 character heights */ static LRESULT MultiInputDialog( HINSTANCE hinst, HWND hwndOwner, char * ptext[], int numlines, int width, int tb_cnt, struct txtbox * tb) { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar, i, pwid; char * p; hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096); if (!hgbl) return -1; mid_cnt = tb_cnt; mid_tb = tb; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_CENTER | DS_SETFOREGROUND | DS_3DLOOK | DS_SHELLFONT | DS_NOFAILCREATE; lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls lpdt->x = 10; lpdt->y = 10; lpdt->cx = 20 + width * 4; lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 8; // font size (points) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg", -1, lpwsz, 128); lpw += nchar; //----------------------- // Define an OK button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)/4 - 20; lpdit->y = 10 + (numlines + tb_cnt + 2) * 14; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDOK; // OK button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data //----------------------- // Define an Cancel button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)*3/4 - 20; lpdit->y = 10 + (numlines + tb_cnt + 2) * 14; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDCANCEL; // CANCEL button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data /* Add controls for preface data */ for ( i=0; istyle = WS_CHILD | WS_VISIBLE | SS_LEFT; lpdit->dwExtendedStyle = 0; lpdit->x = 10; lpdit->y = 10 + i * 14; lpdit->cx = strlen(ptext[i]) * 4 + 10; lpdit->cy = 14; lpdit->id = ID_TEXT + i; // text identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i], -1, lpwsz, 2*width); lpw += nchar; *lpw++ = 0; // no creation data } for ( i=0, pwid = 0; istyle = WS_CHILD | WS_VISIBLE | SS_LEFT; lpdit->dwExtendedStyle = 0; lpdit->x = 10; lpdit->y = 10 + (numlines + i + 1) * 14; lpdit->cx = pwid * 4; lpdit->cy = 14; lpdit->id = ID_TEXT + numlines + i; // text identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].t_lbl ? tb[i].t_lbl : "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 0; // no creation data /*----------------------- * Define an edit control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].t_echo == 1 ? 0L : ES_PASSWORD); lpdit->dwExtendedStyle = 0; lpdit->x = 10 + (pwid + 1) * 4; lpdit->y = 10 + (numlines + i + 1) * 14; lpdit->cx = (width - (pwid + 1)) * 4; lpdit->cy = 14; lpdit->id = ID_MID_TEXT + i; // identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0081; // edit class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].t_dflt ? tb[i].t_dflt : "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 0; // no creation data } GlobalUnlock(hgbl); ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) MultiInputDialogProc); GlobalFree(hgbl); switch ( ret ) { case 0: /* Timeout */ return -1; case IDOK: return 1; case IDCANCEL: return 0; default: { char buf[256]; ckmakmsg(buf,256,"DialogBoxIndirect() failed ",ckitoa(GetLastError()), NULL, NULL); MessageBox(hwndOwner, buf, "GetLastError()", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); return -1; } } } int gui_mtxt_dialog(char * preface, int n, struct txtbox tb[]) { int maxwidth = 0; int numlines = 0; int len; char * plines[16], *p = preface ? preface : ""; int i; for ( i=0; i<16; i++ ) plines[i] = NULL; while (*p && numlines < 16) { plines[numlines++] = p; for ( ;*p && *p != '\r' && *p != '\n'; p++ ); if ( *p == '\r' && *(p+1) == '\n' ) { *p++ = '\0'; p++; } else if ( *p == '\n' ) { *p++ = '\0'; } if ( strlen(plines[numlines-1]) > maxwidth ) maxwidth = strlen(plines[numlines-1]); } for ( i=0;i 40 ? 40 : tb[i].t_len); if ( maxwidth < len ) maxwidth = len; } return(MultiInputDialog(hInstance, hwndConsole, plines, numlines, maxwidth, n, tb)); } static BOOL CALLBACK VideoPopupDialogProc( HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch ( message ) { case WM_INITDIALOG: if ( sid_timeout ) { sid_timer = SetTimer( hwndDlg, ID_SID_TIMER, sid_timeout * 1000, NULL); } return TRUE; case WM_COMMAND: switch ( LOWORD(wParam) ) { case IDOK: case IDCANCEL: if ( sid_timeout ) KillTimer(hwndDlg,sid_timer); EndDialog(hwndDlg, LOWORD(wParam)); return TRUE; } break; case WM_TIMER: if ( sid_timeout ) KillTimer(hwndDlg,sid_timer); EndDialog(hwndDlg, 0); return TRUE; } return FALSE; } /* * dialog widths are measured in 1/4 character widths * dialog height are measured in 1/8 character heights */ static LRESULT VideoPopupDialog( HINSTANCE hinst, HWND hwndOwner, videopopup * vp) { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar, i, j; char * p; hgbl = GlobalAlloc(GMEM_ZEROINIT, 8192); if (!hgbl) return -1; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_CENTER | DS_SETFOREGROUND | DS_3DLOOK | DS_SETFONT | DS_NOFAILCREATE; lpdt->cdit = vp->height + 2; // number of controls lpdt->x = 10; lpdt->y = 10; lpdt->cx = 20 + vp->width * 4; lpdt->cy = 20 + (vp->height + 1) * 8 + 14; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128); lpw += nchar; *lpw++ = 8; // font size (points) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Lucida Console", -1, lpwsz, 128); lpw += nchar; //----------------------- // Define an OK button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)/4 - 20; lpdit->y = 10 + (vp->height + 1) * 8; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDOK; // OK button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data //----------------------- // Define an Cancel button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = (lpdt->cx - 14)*3/4 - 20; lpdit->y = 10 + (vp->height + 1) * 8; lpdit->cx = 40; lpdit->cy = 14; lpdit->id = IDCANCEL; // CANCEL button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data /* Add controls for preface data */ for ( i=0; iheight; i++) { /*----------------------- * Define a static text control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; lpdit->dwExtendedStyle = 0; lpdit->x = 10; lpdit->y = 10 + i * 8; lpdit->cx = vp->width * 4 + 10; lpdit->cy = 8; lpdit->id = ID_TEXT + i; // text identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR) lpw; for ( j=0;jwidth && vp->c[i][j];j++ ) *lpwsz++ = vp->c[i][j]; *lpwsz++ = 0; lpw = lpwsz; *lpw++ = 0; // no creation data } GlobalUnlock(hgbl); ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) VideoPopupDialogProc); GlobalFree(hgbl); switch ( ret ) { case 0: /* Timeout */ return -1; case IDOK: return F_KVERB | K_HELP; case IDCANCEL: return 0; default: { char buf[256]; ckmakmsg(buf,256,"DialogBoxIndirect() failed ",ckitoa(GetLastError()), NULL, NULL); MessageBox(hwndOwner, buf, "GetLastError()", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); return -1; } } } int gui_videopopup_dialog(videopopup * vp, int timeout) { int i; sid_timeout = timeout; return(VideoPopupDialog(hInstance, hwndConsole, vp)); } int gui_position(int x, int y) { KuiSetTerminalPosition(x,y); msleep(50); return(1); } int gui_resize_pixels(int x, int y) { KuiSetTerminalSize(x,y); msleep(50); return(1); } int gui_resize_mode(int x) { KuiSetTerminalResizeMode(x); msleep(50); return(1); } int gui_win_run_mode(int x) { KuiSetTerminalRunMode(x); return(1); } int gui_saveas_dialog(char * preface, char * prompt, int fc, char * def, char * result, int rlength) { return KuiDownloadDialog(prompt,def,result,rlength); } int get_gui_window_pos_x(void) { RECT r; if ( GetWindowRect(getHwndKUI(), &r) ) { return r.left; } else return 0; } int get_gui_window_pos_y(void) { RECT r; if ( GetWindowRect(getHwndKUI(), &r) ) { return r.top; } else return 0; } int get_gui_resize_mode(void) { return KuiGetTerminalResizeMode(); } static HWND hwndRichEdit = INVALID_HANDLE_VALUE; static HWND hwndTextDlg = INVALID_HANDLE_VALUE; static HANDLE hRichEditLib = INVALID_HANDLE_VALUE; static BOOL CALLBACK TextDialogProc( HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch ( message ) { case WM_INITDIALOG: if ( sid_timeout ) { sid_timer = SetTimer( hwndDlg, ID_SID_TIMER, sid_timeout * 1000, NULL); } hwndTextDlg = hwndDlg; hwndRichEdit = GetDlgItem( hwndDlg, ID_TEXT ); PostRichEditInitSem(); return TRUE; case WM_COMMAND: switch ( LOWORD(wParam) ) { case IDOK: if ( sid_timeout ) KillTimer(hwndDlg,sid_timer); hwndTextDlg = hwndRichEdit = INVALID_HANDLE_VALUE; EndDialog(hwndDlg, LOWORD(wParam)); PostRichEditCloseSem(); return TRUE; } break; case WM_CLOSE: case WM_TIMER: if ( sid_timeout ) KillTimer(hwndDlg,sid_timer); hwndTextDlg = hwndRichEdit = INVALID_HANDLE_VALUE; EndDialog(hwndDlg, 0); PostRichEditCloseSem(); return TRUE; } return FALSE; } /* * dialog widths are measured in 1/4 character widths * dialog height are measured in 1/8 character heights */ static LRESULT TextPopupDialog( HINSTANCE hinst, HWND hwndOwner, char * title, int h, int w) { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar, i, j, font = 12; char * p; if ( !w ) w = 80; if ( !h ) h = 25; hgbl = GlobalAlloc(GMEM_ZEROINIT, 8192); if (!hgbl) return -1; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_CENTER | DS_SETFOREGROUND | DS_3DLOOK | DS_SETFONT | DS_NOFAILCREATE; lpdt->cdit = 2; // number of controls lpdt->x = 0; lpdt->y = 0; lpdt->cx = 14 + w * 4; lpdt->cy = 32 + h * font; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) lpwsz = (LPWSTR) lpw; /* caption */ nchar = MultiByteToWideChar (CP_ACP, 0, title, -1, lpwsz, 128); lpw += nchar; *lpw++ = font; // font size (points) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Lucida Console", -1, lpwsz, 128); lpw += nchar; /*----------------------- * Define a Rich Edit 2.0 control. *-----------------------*/ lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | WS_VISIBLE; lpdit->dwExtendedStyle = 0; // WS_EX_CLIENTEDGE; lpdit->x = 7; lpdit->y = 7; lpdit->cx = w * 4; lpdit->cy = h * font; lpdit->id = ID_TEXT; lpw = (LPWORD) (lpdit + 1); lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "RichEdit20W", -1, lpwsz, 50); lpw += nchar; lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data //----------------------- // Define an OK button. //----------------------- lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER; lpdit->dwExtendedStyle = 0; lpdit->x = 7 + w * 2 - 25; lpdit->y = 14 + h * font; lpdit->cx = 50; lpdit->cy = 14; lpdit->id = IDOK; // OK button identifier lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50); lpw += nchar; *lpw++ = 0; // no creation data GlobalUnlock(hgbl); ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl, hwndOwner, (DLGPROC) TextDialogProc); GlobalFree(hgbl); switch ( ret ) { case 0: /* Timeout */ return -1; case IDOK: return 1; default: { char buf[256]; ckmakmsg(buf,256,"DialogBoxIndirect() failed ",ckitoa(GetLastError()), NULL, NULL); MessageBox(hwndOwner, buf, "GetLastError()", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); return -1; } } } static struct { char title[256]; int h; int w; } gui_text_params; void gui_text_popup_thread(void * dummy) { TextPopupDialog( hInstance, hwndConsole, gui_text_params.title, gui_text_params.h, gui_text_params.w ); } static USHORT * EditStreamBuffer = NULL; static int EditStreamMaxLen = 0; static int EditStreamLen = 0; static int stream_complete = 0; static DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb ) { start: RequestRichEditMutex(INFINITE); if ( stream_complete && EditStreamLen == 0 ) { *pcb = 0; } else { if ( EditStreamLen == 0 ) { ReleaseRichEditMutex(); Sleep(100); goto start; } if ( cb % 2 == 1 ) cb--; if ( cb >= EditStreamLen * 2 ) { memcpy(pbBuff, EditStreamBuffer, EditStreamLen * 2); *pcb = EditStreamLen * 2; EditStreamLen = 0; } else { int i, j; memcpy(pbBuff, EditStreamBuffer, cb); *pcb = cb; for (i = 0, j = cb / 2; j <= EditStreamLen; i++, j++) { EditStreamBuffer[i] = EditStreamBuffer[j]; } EditStreamLen = i; } } ReleaseRichEditMutex(); return 0; } static EDITSTREAM EditStream = { 0, 0, EditStreamCallback }; int gui_text_popup_create(char * title, int h, int w) { HANDLE thread; if ( hRichEditLib == INVALID_HANDLE_VALUE ) { hRichEditLib = LoadLibrary("riched20.dll"); if ( hRichEditLib == INVALID_HANDLE_VALUE ) { MessageBox(hwndConsole, "The library RICHED20.DLL required for GUI Text Edit controls is not present on this system", "Error", MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); return -1; } } CreateRichEditInitSem( FALSE ); CreateRichEditCloseSem( FALSE ); CreateRichEditMutex(FALSE); stream_complete = 0; gui_text_params.h = h; gui_text_params.w = w; ckstrncpy(gui_text_params.title,title,256); thread = (HANDLE) _beginthread( gui_text_popup_thread, 65535, NULL ) ; if ( thread != INVALID_HANDLE_VALUE ) WaitRichEditInitSem( INFINITE ); CloseRichEditInitSem(); if ( hwndRichEdit != INVALID_HANDLE_VALUE ) { PostMessage(hwndRichEdit, EM_AUTOURLDETECT, (WPARAM) TRUE, (LPARAM) 0); PostMessage(hwndRichEdit, EM_STREAMIN, (WPARAM)SF_TEXT | SF_UNICODE, (LPARAM)&EditStream); } return 0; } int gui_text_popup_append(unsigned short uch) { start: RequestRichEditMutex(INFINITE); if ( EditStreamMaxLen == 0 ) { EditStreamBuffer = malloc(4096 * sizeof(USHORT)); EditStreamMaxLen = 4096; EditStreamLen = 0; } if ( EditStreamLen < EditStreamMaxLen ) { static int found_cr = 0; if ( uch == CR ) { found_cr = 1; EditStreamBuffer[EditStreamLen++] = 0x2028; } else if ( uch == LF ) { if ( !found_cr ) EditStreamBuffer[EditStreamLen++] = 0x2028; found_cr = 0; } else { EditStreamBuffer[EditStreamLen++] = uch; found_cr = 0; } } else { ReleaseRichEditMutex(); Sleep(100); goto start; } ReleaseRichEditMutex(); return 0; } int gui_text_popup_close(void) { if ( hwndTextDlg != INVALID_HANDLE_VALUE ) PostMessage(hwndTextDlg, WM_CLOSE, 0, 0); CloseRichEditCloseSem(); CloseRichEditMutex(); free(EditStreamBuffer); EditStreamBuffer = NULL; EditStreamLen = EditStreamMaxLen = 0; return 0; } int gui_text_popup_wait(int seconds) { RequestRichEditMutex(INFINITE); stream_complete = 1; ReleaseRichEditMutex(); if ( hwndRichEdit != INVALID_HANDLE_VALUE ) { WaitRichEditCloseSem(seconds == -1 ? INFINITE : seconds * 1000); return 0; } return -1; } #endif /* KUI */