// // Copyright (c) 2013 _iTo_ // #include #include #include "iTerm.h" // Thredモード #define THRED typedef struct argData { HWND hWnd; TCHAR *dispBuf; // 入力データバッファ HFONT hFont; long startLine; TCHAR *dispPrt[PTR]; // 表示行の先頭バッファ DWORD ydspp; // 全体の行数 int xp; // x座標 boolean display; boolean thredExec; }ARGDATA,*PARGDATA; TCHAR ipAdressString[32]; TCHAR ipPortString[12]; void SetCursol(HWND hWnd, int xp, int yp){ SetCaretPos(xp*CARAWIDE,yp*LINEWIDE); ShowCaret(hWnd); } DWORD memRolling(DWORD xdspp, DWORD ydspp, TCHAR *dispBuf, TCHAR *dispPrt[], int *xp) { DWORD w_ydspp; xdspp++; // 次の表示バッファポインタを指す (*xp)++; // カーソルのx座標を指す if(xdspp > MEMSIZE){ // 次の文字がバッファサイズを超えてしまうのならば、メモリの先頭から再利用する w_ydspp = ydspp%PTR; (*xp) = xdspp = 1; // メモリサイズを超えた直後には、1文字入力されている memcpy(dispBuf,&dispBuf[MEMSIZE],1); // 最終行の文字を先頭バッファへ移す dispPrt[w_ydspp] = &dispBuf[0]; // 最終行を先頭ポインターにする } dispBuf[xdspp] = NULL; return xdspp; } DWORD dispCr(DWORD xdspp, ARGDATA *argdatap,SCROLLINFO *scrp) { xdspp = memRolling(xdspp,argdatap->ydspp,argdatap->dispBuf,argdatap->dispPrt,&argdatap->xp); argdatap->xp=0; argdatap->ydspp++; argdatap->dispPrt[argdatap->ydspp%PTR] = &argdatap->dispBuf[xdspp]; // 次の先頭行ポインター if(argdatap->ydspp>=MAXLINE){ // 表示行数を超えた場合、スクロールバーの高さを変更 if(scrp->nPage)scrp->nPage -= 1; // スクロールバーの高さを縮める } return xdspp; } DWORD dispBs(DWORD xdspp, ARGDATA *argdatap,SCROLLINFO *scrp) { if(xdspp>0){ xdspp--; if(xdspp>0 && (argdatap->dispBuf[xdspp-1]&0x80) != 0){ // 全角文字ならば、もう1バイト消す xdspp--; argdatap->xp--; } argdatap->dispBuf[xdspp] = NULL; // 1文字消去 if(argdatap->xp>0){ argdatap->xp--; }else{ // 1行減る if(argdatap->ydspp>0) argdatap->ydspp--; if((argdatap->ydspp+1)<=TOTALLINE){ // 表示行数が減った場合、スクロールバーの高さを変更 if(scrp->nMax>=scrp->nPage)scrp->nPage += 1; // スクロールバーの高さを増やす scrp->nPos = argdatap->ydspp+1-MAXLINE; // スクロールバーを一番下に位置する scrp->fMask = SIF_PAGE | SIF_RANGE | SIF_POS; SetScrollInfo(argdatap->hWnd , SB_VERT , scrp , true); } argdatap->xp = strlen(argdatap->dispPrt[argdatap->ydspp%PTR]); // 1行削除したとき、最終行となった行の最終桁カーソルx座標 } } return xdspp; } #ifdef THRED DWORD WINAPI ThreadFunc(LPVOID vdParam) { PARGDATA pargdata; HDC hdc; DWORD i; DWORD yptr; static RECT rc; pargdata = (PARGDATA)vdParam; GetClientRect(pargdata->hWnd,&rc); while(pargdata->thredExec){ if(pargdata->display){ if(strlen(pargdata->dispBuf)>=0){ hdc=GetDC(pargdata->hWnd); //BeginPaint(pargdata->hWnd,&ps); SelectObject(hdc, pargdata->hFont); // 画面をクリアする InvalidateRect(pargdata->hWnd,NULL, false); PatBlt(hdc, rc.left, rc.top, rc.right, rc.bottom, PATCOPY); // FillRect(hdc,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH)); int sp = 0; DWORD maxline; maxline = pargdata->ydspp+1; if(maxline>MAXLINE){ sp = maxline-MAXLINE; maxline = MAXLINE; } for(i=0; i < maxline;i++){ yptr = (i+sp+pargdata->startLine)%PTR; TextOut(hdc, 0 , i*LINEWIDE , pargdata->dispPrt[yptr], strlen(pargdata->dispPrt[yptr])); } if(pargdata->startLine<0)maxline=MAXLINE+1; // サイドのスクロールバーが動いたらカーソルは表示しない。 // カーソル作成 CreateCaret(pargdata->hWnd, NULL,CARAWIDE,LINEWIDE); SetCursol(pargdata->hWnd, pargdata->xp, maxline-1); ReleaseDC(pargdata->hWnd, hdc); //EndPaint(pargdata->hWnd , &ps); } pargdata->display = false; // 描画終了 } } ExitThread(true); return 0; } #endif LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { // 画面関連変数 static SCROLLINFO scr; static DWORD xdspp = 0; // 入力データバッファのポインター SCROLLINFO siVal; // Socket I/F static pSocketParam sprm; // Thred I/F static ARGDATA argdata; #ifdef THRED DWORD thId; static HANDLE hThread; #endif // その他 static boolean nego = true; static boolean kanji = false; DWORD loop = 0; DWORD i; unsigned char c; switch(uMsg){ case WM_CREATE: argdata.dispBuf = (TCHAR *)calloc(1,MEMSIZE+0x4); sprm = (pSocketParam)malloc(sizeof(SocketParam)); if(argdata.dispBuf!=NULL && sprm!=NULL){ ZeroMemory(sprm, sizeof(SocketParam)); sprm->hWnd = hWnd; sprm->recvDataSize = 0; if(iTermLogin((HINSTANCE)GetWindowLong( hWnd , GWL_HINSTANCE ), sprm)==0){ // Console Initial argdata.dispPrt[0] = argdata.dispBuf; for(i=1; i < PTR;i++) argdata.dispPrt[i] = (char *)NULL; // 縦のスクロールバー作成 scr.cbSize = sizeof(SCROLLINFO); scr.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; scr.nMin = 0; scr.nMax = MAXLINE*MAXPAGE; scr.nPage = MAXLINE*MAXPAGE+1; // スクロールバーの最大行数 scr.nPos = 0; SetScrollInfo(hWnd , SB_VERT , &scr , true); // フォントの定義 argdata.hFont = CreateFont(18,0,0,0,FW_DONTCARE, FALSE,FALSE,FALSE, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,DEFAULT_PITCH | FF_DONTCARE, TEXT("terminal")); #ifdef THRED argdata.hWnd = hWnd; argdata.display = false; // 表示可否 argdata.thredExec = true; // Thred内で無限ループ hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, (LPVOID)&argdata, 0, &thId); #endif }else{ MessageBox( hWnd, "ログインはやめておこう", "warnning", MB_OK ); SendMessage(hWnd, WM_DESTROY, 0, 0); } }else{ MessageBox( hWnd, "メモリ確保に失敗した", "warnning", MB_OK ); SendMessage(hWnd, WM_DESTROY, 0, 0); } break; case WM_SOCKET_INIT: // iTerm Connect Initial switch (LOWORD(lParam)) { case FD_CONNECT: #ifdef NEGO iTermNegoStart(sprm); #else iTermStart(sprm); #endif break; } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_ABOUT: DialogBox((HINSTANCE)GetWindowLong( hWnd , GWL_HINSTANCE ), MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)About); break; case IDM_EXIT: SendMessage(hWnd, WM_CLOSE, 0, 0); break; } break; case WM_VSCROLL: switch(LOWORD(wParam)) { case SB_TOP: scr.nPos = scr.nMin; break; case SB_BOTTOM: scr.nPos = scr.nMax; break; case SB_LINEUP: if (scr.nPos){ scr.nPos--; argdata.startLine--; } break; case SB_LINEDOWN: if(scr.nPos < (argdata.ydspp+1-MAXLINE) && scr.nPos < scr.nMax){ // 表示内容が一番下でないならば、1段下げる scr.nPos++; if(argdata.startLine<0) argdata.startLine++; } break; case SB_PAGEUP: if(scr.nPos <= MAXLINE){ // 1ページ目に戻ったら、表示する先頭行の位置データを設定する scr.nPos = 0; // バーの位置を一番上に戻す if((argdata.ydspp+1)<=TOTALLINE) argdata.startLine = MAXLINE-(argdata.ydspp+1); // 入力された行数が許容行数(表示可能最大行数)以内ならば、入力データの1番先頭行に戻す else argdata.startLine = MAXLINE-TOTALLINE; // 入力データが許容行数を超えているので、最終行の位置から許容行数分戻す }else{ // 戻ったページが1ページ目で無ければ、1ページ分の行数を差し引く scr.nPos -= MAXLINE; argdata.startLine-= MAXLINE; } break; case SB_PAGEDOWN: scr.nPos += MAXLINE; if(scr.nPos>scr.nMax) scr.nPos = scr.nMax; argdata.startLine+= MAXLINE; if(argdata.startLine>0) argdata.startLine = 0; break; case SB_THUMBPOSITION: // バーを放した break; case SB_THUMBTRACK: // バーをドラック中 ZeroMemory( &siVal, sizeof( SCROLLINFO ) ); siVal.cbSize = sizeof( SCROLLINFO ); siVal.fMask = SIF_ALL; GetScrollInfo( hWnd, SB_VERT, &siVal ); if((argdata.ydspp+1)>TOTALLINE) argdata.startLine = siVal.nTrackPos-(scr.nMax); else argdata.startLine = (siVal.nTrackPos+MAXLINE)-(argdata.ydspp+1); scr.nPos = siVal.nTrackPos; break; default: break; } SetScrollInfo(hWnd , SB_VERT , &scr , true); #ifdef THRED argdata.display = true; #else InvalidateRect(hWnd , NULL , true); #endif break; case WM_CHAR: // iTerm Send sprm->sendData[0] = (char)wParam; sprm->sendDataSize = 1; case WM_NEGO: iTermSend(sprm,nego); break; case WM_SOCKET_RECV: // iTerm Recive switch (LOWORD(lParam)) { case FD_READ: // TCP/IP while(true){ iTermRecv(sprm); if(sprm->recvDataSize>0){ #ifdef THRED while(argdata.display)Sleep(1); // 描画終了待ち #endif if(nego && sprm->recvData[0] != NEGO_IAC){ nego = false; // Telnetのネゴシエーション終了 } for(loop=0; loop < sprm->recvDataSize;loop++){ if(nego && loop == 0 && sprm->recvData[loop] == NEGO_IAC){ // ネゴシエーション処理 nego = iTermNegotiation(nego, sprm, &loop); if(nego){ sprm->recvDataSize = 0; SendMessage(hWnd , WM_NEGO , 0 , 0); } } if(loop >= sprm->recvDataSize)break; if(!nego){ c = sprm->recvData[loop]; if((0x81<=c&&c<=0x9f)||(0xe0<=c&&c<=0xef)) kanji = true; // 全角上位8bit if((0x00<=c&&c<=0x1f)||(0x20<=c&&c<=0x7f)||(0xa1<=c&&c<=0xdf)||kanji){ // 半角文字 if((0x40<=c&&c<=0x7e)||(0x80<=c&&c<=0xfc)) kanji = false; // 全角下位8bit if(c == LF){ // LF // 水平位置を維持したままで次のラインに移動。 }else if(c == CR){ // CR xdspp = dispCr(xdspp,&argdata,&scr); }else if(c == BS){ // BS xdspp = dispBs(xdspp,&argdata,&scr); }else if((0x00<=c&&c<=0x1f)||c==0x7f){ // 制御コード if((loop+1recvDataSize)&&(c==0x1b && sprm->recvData[loop+1]=='[')){ // エスケープシーケンス loop++;loop++; // ポイントを'['の次に進める while(true){ for(i=0;(looprecvDataSize)&&(('0'<=sprm->recvData[loop] && sprm->recvData[loop]<='9') || sprm->recvData[loop]=='?' || sprm->recvData[loop]=='H');loop++,i++); for(i=0;(looprecvDataSize)&&(sprm->recvData[loop]==';' || sprm->recvData[loop]=='g' || sprm->recvData[loop]=='h' || sprm->recvData[loop]=='l' || sprm->recvData[loop]=='J' || sprm->recvData[loop]=='K');loop++,i++); if(i==0) break; } for(;(looprecvDataSize)&&('A'<=sprm->recvData[loop] && sprm->recvData[loop]<='E');loop++); loop--; // 外側のforでloop++してるので1つポイントを戻す xdspp = dispCr(xdspp,&argdata,&scr); // CR } }else{ wsprintf( &argdata.dispBuf[xdspp], _T("%c"), c ); xdspp = memRolling(xdspp,argdata.ydspp,argdata.dispBuf,argdata.dispPrt,&argdata.xp); } } } } if(!nego){ sprm->recvDataSize = 0; #ifdef THRED argdata.display = true; // 描画開始 #endif // キー入力が有れば表示位置を一番下に戻す argdata.startLine = 0; if(scr.nPos=0){ HDC hdc; PAINTSTRUCT ps; hdc=BeginPaint(hWnd,&ps); SelectObject(hdc, argdata.hFont); int sp = 0; DWORD maxline; DWORD yptr; maxline = argdata.ydspp+1; if(maxline>MAXLINE){ sp = maxline-MAXLINE; maxline = MAXLINE; } for(i=0; i < maxline;i++){ yptr = (i+sp+argdata.startLine)%PTR; TextOut(hdc, 0 , i*LINEWIDE , argdata.dispPrt[yptr], strlen(argdata.dispPrt[yptr])); } if(argdata.startLine<0)maxline=MAXLINE+1; // サイドのスクロールバーが動いたらカーソルは表示しない。 // カーソル作成 CreateCaret(hWnd, NULL,CARAWIDE,LINEWIDE); SetCursol(hWnd,argdata.xp,maxline-1); EndPaint(hWnd , &ps); } #endif break; case WM_DESTROY: #ifdef THRED argdata.thredExec = false; CloseHandle(hThread); #endif iTermClose(sprm); free(argdata.dispBuf); DestroyCaret(); DeleteObject(argdata.hFont); PostQuitMessage(0); break; } return DefWindowProc(hWnd,uMsg,wParam,lParam); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR lpCmdLine,int nCmdShow) { MSG msg; int ret; WNDCLASSEX wc; wc.cbSize = sizeof(wc); // 構造体サイズ wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); // アイコン wc.hIconSm = wc.hIcon; // 子アイコン wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_IBEAM), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); // マウスカーソル wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //NULL; wc.lpszMenuName = "ITERMMENU"; wc.lpszClassName = _T("Default Class Name"); if(!RegisterClassEx(&wc)) return 0; HWND hWnd=CreateWindow( wc.lpszClassName,"iTerm", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT,CW_USEDEFAULT, 34+(CARAWIDE*MAXCOLUMN),38+(LINEWIDE*MAXLINE)+LINEWIDE, // CW_USEDEFAULT,CW_USEDEFAULT, NULL,NULL,hInstance,NULL); if(hWnd==NULL) return 0; while((ret=GetMessage(&msg,NULL,0,0))!=0){ if(ret==-1) break; TranslateMessage(&msg); // これを使うとWM_CHARのメッセージが発生する。 DispatchMessage(&msg); } return (int)msg.wParam; }