/** * 개별 프로세서의 정보를 화면에 표시 */ static void kDrawProcessorInformation( QWORD qwWindowID, int iX, int iY, BYTE bAPICID ) { char vcBuffer[ 100 ]; RECT stArea; QWORD qwProcessorLoad; QWORD iUsageBarHeight; int iMiddleX; // 프로세서 ID를 표시 kSPrintf( vcBuffer, "Processor ID: %d", bAPICID ); kDrawText( qwWindowID, iX + 10, iY, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcBuffer, kStrLen( vcBuffer ) ); // 프로세서의 태스크 개수를 표시 kSPrintf( vcBuffer, "Task Count: %d ", kGetTaskCount( bAPICID ) ); kDrawText( qwWindowID, iX + 10, iY + 18, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcBuffer, kStrLen( vcBuffer ) ); //-------------------------------------------------------------------------- // 프로세서 부하를 나타내는 막대를 표시 //-------------------------------------------------------------------------- // 프로세서 부하를 표시 qwProcessorLoad = kGetProcessorLoad( bAPICID ); if( qwProcessorLoad > 100 ) { qwProcessorLoad = 100; } // 부하를 표시하는 막대의 전체에 테두리를 표시 kDrawRect( qwWindowID, iX, iY + 36, iX + SYSTEMMONITOR_PROCESSOR_WIDTH, iY + SYSTEMMONITOR_PROCESSOR_HEIGHT, RGB( 0, 0, 0 ), FALSE ); // 프로세서 사용량을 나타내는 막대의 길이, ( 막대 전체의 길이 * 프로세서 부하 / 100 ) iUsageBarHeight = ( SYSTEMMONITOR_PROCESSOR_HEIGHT - 40 ) * qwProcessorLoad / 100; // 부하를 표시하는 영역의 막대 내부를 표시 // 채워진 막대를 표시, 테두리와 2픽셀 정도 여유 공간을 둠 kDrawRect( qwWindowID, iX + 2, iY + ( SYSTEMMONITOR_PROCESSOR_HEIGHT - iUsageBarHeight ) - 2, iX + SYSTEMMONITOR_PROCESSOR_WIDTH - 2, iY + SYSTEMMONITOR_PROCESSOR_HEIGHT - 2, SYSTEMMONITOR_BAR_COLOR, TRUE ); // 빈 막대를 표시, 테두리와 2픽셀 정도 여유 공간을 둠 kDrawRect( qwWindowID, iX + 2, iY + 38, iX + SYSTEMMONITOR_PROCESSOR_WIDTH - 2, iY + ( SYSTEMMONITOR_PROCESSOR_HEIGHT - iUsageBarHeight ) - 1, WINDOW_COLOR_BACKGROUND, TRUE ); // 프로세서의 부하를 표시, 막대의 가운데에 부하가 표시되도록 함 kSPrintf( vcBuffer, "Usage: %d%%", qwProcessorLoad ); iMiddleX = ( SYSTEMMONITOR_PROCESSOR_WIDTH - ( kStrLen( vcBuffer ) * FONT_ENGLISHWIDTH ) ) / 2; kDrawText( qwWindowID, iX + iMiddleX, iY + 80, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcBuffer, kStrLen( vcBuffer ) ); // 프로세서 정보가 표시된 영역만 다시 화면에 업데이트 kSetRectangleData( iX, iY, iX + SYSTEMMONITOR_PROCESSOR_WIDTH, iY + SYSTEMMONITOR_PROCESSOR_HEIGHT, &stArea ); kUpdateScreenByWindowArea( qwWindowID, &stArea ); }
// 파일을 생성 static BOOL kCreateFile(const char* pcFileName,DIRECTORYENTRY* pstEntry,int* piDirectoryEntryIndex) { DWORD dwCluster; // 빈 클러스터를 찾아서 할당된 것으로 설정 dwCluster = kFindFreeCluster(); if((dwCluster==FILESYSTEM_LASTCLUSTER)||(kSetClusterLinkData(dwCluster,FILESYSTEM_LASTCLUSTER)==FALSE)) { return FALSE; } // 빈 디렉터리 엔트리를 검색 *piDirectoryEntryIndex = kFindFreeDirectoryEntry(); if(*piDirectoryEntryIndex==-1) { // 실패하면 할당받은 클러스터를 반환해야 함 kSetClusterLinkData(dwCluster,FILESYSTEM_FREECLUSTER); return FALSE; } // 디렉터리 엔트리를 설정 kMemCpy(pstEntry->vcFileName,pcFileName,kStrLen(pcFileName)+1); pstEntry->dwStartClusterIndex = dwCluster; pstEntry->dwFileSize = 0; // 디렉터리 엔트리를 등록 if(kSetDirectoryEntryData(*piDirectoryEntryIndex,pstEntry)==FALSE) { // 실패하여 할당받은 클러스털르 반환해야 함 kSetClusterLinkData(dwCluster,FILESYSTEM_FREECLUSTER); return FALSE; } return TRUE; }
// 루트 디렉터리에서 파일 이름이 일치하는 엔트리를 찾아서 인덱스를 반환 static int kFindDirectoryEntry(const char* pcFileName,DIRECTORYENTRY* pstEntry) { DIRECTORYENTRY* pstRootEntry; int i; int iLength; // 파일 시스템을 인식하지 못했으면 실패 if(gs_stFileSystemManager.bMounted==FALSE) { return -1; } // 루트 디렉터리를 읽음 if(kReadCluster(0,gs_vbTempBuffer)==FALSE) { return -1; } iLength = kStrLen(pcFileName); // 루트 디렉터리 안에서 루프를 돌면서 파일 이름이 일치하는 엔트리를 반환 pstRootEntry = (DIRECTORYENTRY*)gs_vbTempBuffer; for(i=0;i<FILESYSTEM_MAXDIRECTORYENTRYCOUNT;i++) { if(kMemCmp(pstRootEntry[i].vcFileName,pcFileName,iLength)==0) { kMemCpy(pstEntry,pstRootEntry+i,sizeof(DIRECTORYENTRY)); return i; } } return -1; }
/** * \n, \t와 같은 문자가 포함된 문자열을 출력한 후, 화면상의 다음 출력할 위치를 * 반환 */ int kConsolePrintString( const char* pcBuffer ) { CHARACTER* pstScreen = ( CHARACTER* ) CONSOLE_VIDEOMEMORYADDRESS; int i, j; int iLength; int iPrintOffset; // 문자열을 출력할 위치를 저장 iPrintOffset = gs_stConsoleManager.iCurrentPrintOffset; // 문자열의 길이만큼 화면에 출력 iLength = kStrLen( pcBuffer ); for( i = 0 ; i < iLength ; i++ ) { // 개행 처리 if( pcBuffer[ i ] == '\n' ) { // 출력할 위치를 80의 배수 컬럼으로 옮김 // 현재 라인의 남은 문자열의 수만큼 더해서 다음 라인으로 위치시킴 iPrintOffset += ( CONSOLE_WIDTH - ( iPrintOffset % CONSOLE_WIDTH ) ); } // 탭 처리 else if( pcBuffer[ i ] == '\t' ) { // 출력할 위치를 8의 배수 컬럼으로 옮김 iPrintOffset += ( 8 - ( iPrintOffset % 8 ) ); } // 일반 문자열 출력 else { // 비디오 메모리에 문자와 속성을 설정하여 문자를 출력하고 // 출력할 위치를 다음으로 이동 pstScreen[ iPrintOffset ].bCharactor = pcBuffer[ i ]; pstScreen[ iPrintOffset ].bAttribute = CONSOLE_DEFAULTTEXTCOLOR; iPrintOffset++; } // 출력할 위치가 화면의 최댓값(80 * 25)을 벗어났으면 스크롤 처리 if( iPrintOffset >= ( CONSOLE_HEIGHT * CONSOLE_WIDTH ) ) { // 가장 윗줄을 제외한 나머지를 한줄 위로 복사 kMemCpy( CONSOLE_VIDEOMEMORYADDRESS, CONSOLE_VIDEOMEMORYADDRESS + CONSOLE_WIDTH * sizeof( CHARACTER ), ( CONSOLE_HEIGHT - 1 ) * CONSOLE_WIDTH * sizeof( CHARACTER ) ); // 가장 마지막 라인은 공백으로 채움 for( j = ( CONSOLE_HEIGHT - 1 ) * ( CONSOLE_WIDTH ) ; j < ( CONSOLE_HEIGHT * CONSOLE_WIDTH ) ; j++ ) { // 공백 출력 pstScreen[ j ].bCharactor = ' '; pstScreen[ j ].bAttribute = CONSOLE_DEFAULTTEXTCOLOR; } // 출력할 위치를 가장 아래쪽 라인의 처음으로 설정 iPrintOffset = ( CONSOLE_HEIGHT - 1 ) * CONSOLE_WIDTH; } } return iPrintOffset; }
//============================================================================= // Process command //============================================================================= // Help void kHelp( const char * pcCommandBuffer ) { int i; int iCount; int iCursorX, iCursorY; int iLength, iMaxCommandLength = 0; kPrintf( "======================================================================\n" ); kPrintf( " KARLINUX SHELL HELP \n" ); kPrintf( "======================================================================\n" ); iCount = sizeof( gs_vstCommandTable ) / sizeof( SHELLCOMMANDENTRY ); // Calculate length of longest command for ( i = 0 ; i < iCount ; i++ ) { iLength = kStrLen( gs_vstCommandTable[i].pcCommand ); if ( iLength > iMaxCommandLength ) { iMaxCommandLength = iLength; } } // Print help for ( i = 0 ; i < iCount ; i++ ) { kPrintf( "%s", gs_vstCommandTable[i].pcCommand ); kGetCursor( &iCursorX, &iCursorY ); kSetCursor( iMaxCommandLength, iCursorY ); kPrintf( " - %s\n", gs_vstCommandTable[i].pcHelp ); } }
/** * 셸 도움말을 출력 */ void kHelp( const char* pcCommandBuffer ) { int i; int iCount; int iCursorX, iCursorY; int iLength, iMaxCommandLength = 0; kPrintf( "=========================================================\n" ); kPrintf( " MINT64 Shell Help \n" ); kPrintf( "=========================================================\n" ); iCount = sizeof( gs_vstCommandTable ) / sizeof( SHELLCOMMANDENTRY ); // 가장 긴 커맨드의 길이를 계산 for( i = 0 ; i < iCount ; i++ ) { iLength = kStrLen( gs_vstCommandTable[ i ].pcCommand ); if( iLength > iMaxCommandLength ) { iMaxCommandLength = iLength; } } // 도움말 출력 for( i = 0 ; i < iCount ; i++ ) { kPrintf( "%s", gs_vstCommandTable[ i ].pcCommand ); kGetCursor( &iCursorX, &iCursorY ); kSetCursor( iMaxCommandLength, iCursorY ); kPrintf( " - %s\n", gs_vstCommandTable[ i ].pcHelp ); } }
// 파일을 삭제 int kRemoveFile(const char* pcFileName) { DIRECTORYENTRY stEntry; int iDirectoryEntryOffset; int iFileNameLength; // 파일 이름 검사 iFileNameLength = kStrLen(pcFileName); if((iFileNameLength>(sizeof(stEntry.vcFileName)-1))||(iFileNameLength==0)) { return NULL; } // 동기화 kLock(&(gs_stFileSystemManager.stMutex)); // 파일이 존재하는지 확인 iDirectoryEntryOffset = kFindDirectoryEntry(pcFileName,&stEntry); if(iDirectoryEntryOffset==-1) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return -1; } // 다른 태스크에서 해당 파일을 열고 있는지 핸들 풀을 검색하여 확인 파일이 열려 있으면 삭제할 수 없음 if(kIsFileOpened(&stEntry)==TRUE) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return -1; } // 파일을 구성하는 클러스터를 모두 해제 if(kFreeClusterUtilEnd(stEntry.dwStartClusterIndex)==FALSE) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return -1; } // 디렉터리 엔트리를 빈 것으로 설정 kMemSet(&stEntry,0,sizeof(stEntry)); if(kSetDirectoryEntryData(iDirectoryEntryOffset,&stEntry)==FALSE) { // 동긱화 kUnlock(&(gs_stFileSystemManager.stMutex)); return -1; } // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return 0; }
// Execute command if the command is one of the predefined void kExecuteCommand( const char * pcCommandBuffer ) { int i, iSpaceIndex; int iCommandBufferLength, iCommandLength; int iCount; // Extract command iCommandBufferLength = kStrLen( pcCommandBuffer ); for ( iSpaceIndex = 0 ; iSpaceIndex < iCommandBufferLength ; iSpaceIndex++ ) { if( pcCommandBuffer[iSpaceIndex] == ' ' ) { break; } } // Search the command in table iCount = sizeof( gs_vstCommandTable ) / sizeof( SHELLCOMMANDENTRY ); for ( i = 0 ; i < iCount ; i++ ) { iCommandLength = kStrLen( gs_vstCommandTable[i].pcCommand ); // Compare length and command if ( ( iCommandLength == iSpaceIndex ) && ( kMemCmp( gs_vstCommandTable[i].pcCommand, pcCommandBuffer, iSpaceIndex ) == 0 ) ) { gs_vstCommandTable[i].pfFunction( pcCommandBuffer + iSpaceIndex + 1 ); break; } } // If there is not same command if ( i >= iCount ) { kPrintf( "'%s' is not found.\n", pcCommandBuffer ); } }
/* * 커맨드 버퍼에 있는 커맨드를 비교하여 해당 커맨드를 처리하는 함수를 수행 */ void kExecuteCommand( const char* pcCommandBuffer ) { int i, iSpaceIndex; int iCommandBufferLength, iCommandLength; int iCount; // 공백으로 구분된 커맨드를 추출 iCommandBufferLength = kStrLen( pcCommandBuffer ); for( iSpaceIndex = 0 ; iSpaceIndex < iCommandBufferLength ; iSpaceIndex++ ) { if( pcCommandBuffer[ iSpaceIndex ] == ' ' ) { break; } } // 커맨드 테이블을 검사해서 동일한 이름의 커맨드가 있는지 확인 iCount = sizeof( gs_vstCommandTable ) / sizeof( SHELLCOMMANDENTRY ); for( i = 0 ; i < iCount ; i++ ) { iCommandLength = kStrLen( gs_vstCommandTable[ i ].pcCommand ); // 커맨드의 길이와 내용이 완전히 일치하는지 검사 if( ( iCommandLength == iSpaceIndex ) && ( kMemCmp( gs_vstCommandTable[ i ].pcCommand, pcCommandBuffer, iSpaceIndex ) == 0 ) ) { gs_vstCommandTable[ i ].pfFunction( pcCommandBuffer + iSpaceIndex + 1 ); break; } } // 리스트에서 찾을 수 없다면 에러 출력 if( i >= iCount ) { kPrintf( "'%s' is not found.\n", pcCommandBuffer ); } }
/** * 셸 도움말을 출력 */ static void kHelp( const char* pcCommandBuffer ) { int i; int iCount; int iCursorX, iCursorY; int iLength, iMaxCommandLength = 0; kPrintf( "=========================================================\n" ); kPrintf( " MINT64 Shell Help \n" ); kPrintf( "=========================================================\n" ); iCount = sizeof( gs_vstCommandTable ) / sizeof( SHELLCOMMANDENTRY ); // 가장 긴 커맨드의 길이를 계산 for( i = 0 ; i < iCount ; i++ ) { iLength = kStrLen( gs_vstCommandTable[ i ].pcCommand ); if( iLength > iMaxCommandLength ) { iMaxCommandLength = iLength; } } // 도움말 출력 for( i = 0 ; i < iCount ; i++ ) { kPrintf( "%s", gs_vstCommandTable[ i ].pcCommand ); kGetCursor( &iCursorX, &iCursorY ); kSetCursor( iMaxCommandLength, iCursorY ); kPrintf( " - %s\n", gs_vstCommandTable[ i ].pcHelp ); // 목록이 많을 경우 나눠서 보여줌 if( ( i != 0 ) && ( ( i % 20 ) == 0 ) ) { kPrintf( "Press any key to continue... ('q' is exit) : " ); if( kGetCh() == 'q' ) { kPrintf( "\n" ); break; } kPrintf( "\n" ); } } }
/** * Hello World GUI 태스크 */ void kHelloWorldGUITask( void ) { QWORD qwWindowID; int iMouseX, iMouseY; int iWindowWidth, iWindowHeight; EVENT stReceivedEvent; MOUSEEVENT* pstMouseEvent; KEYEVENT* pstKeyEvent; WINDOWEVENT* pstWindowEvent; int iY; char vcTempBuffer[ 50 ]; static int s_iWindowCount = 0; // 이벤트 타입 문자열 char* vpcEventString[] = { "Unknown", "MOUSE_MOVE ", "MOUSE_LBUTTONDOWN", "MOUSE_LBUTTONUP ", "MOUSE_RBUTTONDOWN", "MOUSE_RBUTTONUP ", "MOUSE_MBUTTONDOWN", "MOUSE_MBUTTONUP ", "WINDOW_SELECT ", "WINDOW_DESELECT ", "WINDOW_MOVE ", "WINDOW_RESIZE ", "WINDOW_CLOSE ", "KEY_DOWN ", "KEY_UP " }; RECT stButtonArea; QWORD qwFindWindowID; EVENT stSendEvent; int i; //-------------------------------------------------------------------------- // 그래픽 모드 판단 //-------------------------------------------------------------------------- // MINT64 OS가 그래픽 모드로 시작했는지 확인 if( kIsGraphicMode() == FALSE ) { // MINT64 OS가 그래픽 모드로 시작하지 않았다면 실패 kPrintf( "This task can run only GUI mode~!!!\n" ); return ; } //-------------------------------------------------------------------------- // 윈도우를 생성 //-------------------------------------------------------------------------- // 마우스의 현재 위치를 반환 kGetCursorPosition( &iMouseX, &iMouseY ); // 윈도우의 크기와 제목 설정 iWindowWidth = 500; iWindowHeight = 200; // 윈도우 생성 함수 호출, 마우스가 있던 위치를 기준으로 생성하고 번호를 추가하여 // 윈도우마다 개별적인 이름을 할당 kSPrintf( vcTempBuffer, "Hello World Window %d", s_iWindowCount++ ); qwWindowID = kCreateWindow( iMouseX - 10, iMouseY - WINDOW_TITLEBAR_HEIGHT / 2, iWindowWidth, iWindowHeight, WINDOW_FLAGS_DEFAULT, vcTempBuffer ); // 윈도우를 생성하지 못했으면 실패 if( qwWindowID == WINDOW_INVALIDID ) { return ; } //-------------------------------------------------------------------------- // 윈도우 매니저가 윈도우로 전송하는 이벤트를 표시하는 영역을 그림 //-------------------------------------------------------------------------- // 이벤트 정보를 출력할 위치 저장 iY = WINDOW_TITLEBAR_HEIGHT + 10; // 이벤트 정보를 표시하는 영역의 테두리와 윈도우 ID를 표시 kDrawRect( qwWindowID, 10, iY + 8, iWindowWidth - 10, iY + 70, RGB( 0, 0, 0 ), FALSE ); kSPrintf( vcTempBuffer, "GUI Event Information[Window ID: 0x%Q]", qwWindowID ); kDrawText( qwWindowID, 20, iY, RGB( 0, 0, 0 ), RGB( 255, 255, 255 ), vcTempBuffer, kStrLen( vcTempBuffer ) ); //-------------------------------------------------------------------------- // 화면 아래에 이벤트 전송 버튼을 그림 //-------------------------------------------------------------------------- // 버튼 영역을 설정 kSetRectangleData( 10, iY + 80, iWindowWidth - 10, iWindowHeight - 10, &stButtonArea ); // 배경은 윈도우의 배경색으로 설정하고 문자는 검은색으로 설정하여 버튼을 그림 kDrawButton( qwWindowID, &stButtonArea, WINDOW_COLOR_BACKGROUND, "User Message Send Button(Up)", RGB( 0, 0, 0 ) ); // 윈도우를 화면에 표시 kShowWindow( qwWindowID, TRUE ); //-------------------------------------------------------------------------- // GUI 태스크의 이벤트 처리 루프 //-------------------------------------------------------------------------- while( 1 ) { // 이벤트 큐에서 이벤트를 수신 if( kReceiveEventFromWindowQueue( qwWindowID, &stReceivedEvent ) == FALSE ) { kSleep( 0 ); continue; } // 윈도우 이벤트 정보가 표시될 영역을 배경색으로 칠하여 이전에 표시한 데이터를 // 모두 지움 kDrawRect( qwWindowID, 11, iY + 20, iWindowWidth - 11, iY + 69, WINDOW_COLOR_BACKGROUND, TRUE ); // 수신된 이벤트를 타입에 따라 나누어 처리 switch( stReceivedEvent.qwType ) { // 마우스 이벤트 처리 case EVENT_MOUSE_MOVE: case EVENT_MOUSE_LBUTTONDOWN: case EVENT_MOUSE_LBUTTONUP: case EVENT_MOUSE_RBUTTONDOWN: case EVENT_MOUSE_RBUTTONUP: case EVENT_MOUSE_MBUTTONDOWN: case EVENT_MOUSE_MBUTTONUP: // 여기에 마우스 이벤트 처리 코드 넣기 pstMouseEvent = &( stReceivedEvent.stMouseEvent ); // 마우스 이벤트의 타입을 출력 kSPrintf( vcTempBuffer, "Mouse Event: %s", vpcEventString[ stReceivedEvent.qwType ] ); kDrawText( qwWindowID, 20, iY + 20, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); // 마우스 데이터를 출력 kSPrintf( vcTempBuffer, "Data: X = %d, Y = %d, Button = %X", pstMouseEvent->stPoint.iX, pstMouseEvent->stPoint.iY, pstMouseEvent->bButtonStatus ); kDrawText( qwWindowID, 20, iY + 40, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); //------------------------------------------------------------------ // 마우스 눌림 또는 떨어짐 이벤트이면 버튼의 색깔을 다시 그림 //------------------------------------------------------------------ // 마우스 왼쪽 버튼이 눌렸을 때 버튼 처리 if( stReceivedEvent.qwType == EVENT_MOUSE_LBUTTONDOWN ) { // 버튼 영역에 마우스 왼쪽 버튼이 눌렸는지를 판단 if( kIsInRectangle( &stButtonArea, pstMouseEvent->stPoint.iX, pstMouseEvent->stPoint.iY ) == TRUE ) { // 버튼의 배경을 밝은 녹색으로 변경하여 눌렸음을 표시 kDrawButton( qwWindowID, &stButtonArea, RGB( 79, 204, 11 ), "User Message Send Button(Down)", RGB( 255, 255, 255 ) ); kUpdateScreenByID( qwWindowID ); //---------------------------------------------------------- // 다른 윈도우로 유저 이벤트를 전송 //---------------------------------------------------------- // 생성된 모든 윈도우를 찾아서 이벤트를 전송 stSendEvent.qwType = EVENT_USER_TESTMESSAGE; stSendEvent.vqwData[ 0 ] = qwWindowID; stSendEvent.vqwData[ 1 ] = 0x1234; stSendEvent.vqwData[ 2 ] = 0x5678; // 생성된 윈도우의 수 만큼 루프를 수행하면서 이벤트를 전송 for( i = 0 ; i < s_iWindowCount ; i++ ) { // 윈도우 제목으로 윈도우를 검색 kSPrintf( vcTempBuffer, "Hello World Window %d", i ); qwFindWindowID = kFindWindowByTitle( vcTempBuffer ); // 윈도우가 존재하며 윈도우 자신이 아닌 경우는 이벤트를 전송 if( ( qwFindWindowID != WINDOW_INVALIDID ) && ( qwFindWindowID != qwWindowID ) ) { // 윈도우로 이벤트 전송 kSendEventToWindow( qwFindWindowID, &stSendEvent ); } } } } // 마우스 왼쪽 버튼이 떨어졌을 때 버튼 처리 else if( stReceivedEvent.qwType == EVENT_MOUSE_LBUTTONUP ) { // 버튼의 배경을 흰색으로 변경하여 눌리지 않았음을 표시 kDrawButton( qwWindowID, &stButtonArea, WINDOW_COLOR_BACKGROUND, "User Message Send Button(Up)", RGB( 0, 0, 0 ) ); } break; // 키 이벤트 처리 case EVENT_KEY_DOWN: case EVENT_KEY_UP: // 여기에 키보드 이벤트 처리 코드 넣기 pstKeyEvent = &( stReceivedEvent.stKeyEvent ); // 키 이벤트의 타입을 출력 kSPrintf( vcTempBuffer, "Key Event: %s", vpcEventString[ stReceivedEvent.qwType ] ); kDrawText( qwWindowID, 20, iY + 20, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); // 키 데이터를 출력 kSPrintf( vcTempBuffer, "Data: Key = %c, Flag = %X", pstKeyEvent->bASCIICode, pstKeyEvent->bFlags ); kDrawText( qwWindowID, 20, iY + 40, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); break; // 윈도우 이벤트 처리 case EVENT_WINDOW_SELECT: case EVENT_WINDOW_DESELECT: case EVENT_WINDOW_MOVE: case EVENT_WINDOW_RESIZE: case EVENT_WINDOW_CLOSE: // 여기에 윈도우 이벤트 처리 코드 넣기 pstWindowEvent = &( stReceivedEvent.stWindowEvent ); // 윈도우 이벤트의 타입을 출력 kSPrintf( vcTempBuffer, "Window Event: %s", vpcEventString[ stReceivedEvent.qwType ] ); kDrawText( qwWindowID, 20, iY + 20, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); // 윈도우 데이터를 출력 kSPrintf( vcTempBuffer, "Data: X1 = %d, Y1 = %d, X2 = %d, Y2 = %d", pstWindowEvent->stArea.iX1, pstWindowEvent->stArea.iY1, pstWindowEvent->stArea.iX2, pstWindowEvent->stArea.iY2 ); kDrawText( qwWindowID, 20, iY + 40, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); //------------------------------------------------------------------ // 윈도우 닫기 이벤트이면 윈도우를 삭제하고 루프를 빠져나가 태스크를 종료 //------------------------------------------------------------------ if( stReceivedEvent.qwType == EVENT_WINDOW_CLOSE ) { // 윈도우 삭제 kDeleteWindow( qwWindowID ); return ; } break; // 그 외 정보 default: // 여기에 알 수 없는 이벤트 처리 코드 넣기 // 알 수 없는 이벤트를 출력 kSPrintf( vcTempBuffer, "Unknown Event: 0x%X", stReceivedEvent.qwType ); kDrawText( qwWindowID, 20, iY + 20, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); // 데이터를 출력 kSPrintf( vcTempBuffer, "Data0 = 0x%Q, Data1 = 0x%Q, Data2 = 0x%Q", stReceivedEvent.vqwData[ 0 ], stReceivedEvent.vqwData[ 1 ], stReceivedEvent.vqwData[ 2 ] ); kDrawText( qwWindowID, 20, iY + 40, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcTempBuffer, kStrLen( vcTempBuffer ) ); break; } // 윈도우를 화면에 업데이트 kShowWindow( qwWindowID, TRUE ); } }
// 파일을 열거나 생성 FILE* kOpenFile(const char* pcFileName,const char* pcMode) { DIRECTORYENTRY stEntry; int iDirectoryEntryOffset; int iFileNameLength; DWORD dwSecondCluster; FILE* pstFile; // 파일 이름 검사 iFileNameLength = kStrLen(pcFileName); if((iFileNameLength>(sizeof(stEntry.vcFileName)-1))||(iFileNameLength==0)) { return NULL; } // 동기화 kLock(&(gs_stFileSystemManager.stMutex)); //========================================================================================= // 파일이 먼저 존재하는지 확인하고, 없다면 옵션을 보고 파일을 생성 //========================================================================================= iDirectoryEntryOffset = kFindDirectoryEntry(pcFileName,&stEntry); if(iDirectoryEntryOffset==-1) { // 파일이 없다면 읽기(r,r+) 옵션은 실패 if(pcMode[0]=='r') { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return NULL; } // 나머지 옵션은 파일을 생성 if(kCreateFile(pcFileName,&stEntry,&iDirectoryEntryOffset)==FALSE) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return NULL; } } //========================================================================================= // 파일의 내용을 비워야 하는 옵션이면 파일에 연결된 클러스터를 모두 제거하고 파일 크기를 0으로 설정 //========================================================================================= else if(pcMode[0]=='w') { // 시작 클러스터의 다음 클러스터를 찾음 if(kGetClusterLinkData(stEntry.dwStartClusterIndex,&dwSecondCluster)==FALSE) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return NULL; } // 시작 클러스러를 마지막 클러스터로 만듬 if(kSetClusterLinkData(stEntry.dwStartClusterIndex,FILESYSTEM_LASTCLUSTER)==FALSE) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return NULL; } // 다음 클러스터부터 마지막 클러스터까지 모두 해제 if(kFreeClusterUtilEnd(dwSecondCluster)==FALSE) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return NULL; } // 파일의 내용이 모두 비워졌으므로 크기를 0으로 설정 stEntry.dwFileSize = 0; if(kSetDirectoryEntryData(iDirectoryEntryOffset,&stEntry)==FALSE) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return NULL; } } //======================================================================================== // 파일 핸들을 할당받아 데이터를 설정한 후 반환 //======================================================================================== // 파일 핸들을 할당받아 데이터를 설정 pstFile = kAllocateFileDirectoryHandle(); if(pstFile==NULL) { // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return NULL; } // 파일 핸들에 파일 정보를 설정 pstFile->bType = FILESYSTEM_TYPE_FILE; pstFile->stFileHandle.iDirectoryEntryOffset = iDirectoryEntryOffset; pstFile->stFileHandle.dwFileSize = stEntry.dwFileSize; pstFile->stFileHandle.dwStartClusterIndex = stEntry.dwStartClusterIndex; pstFile->stFileHandle.dwCurrentClusterIndex = stEntry.dwStartClusterIndex; pstFile->stFileHandle.dwPreviousClusterIndex= stEntry.dwStartClusterIndex; pstFile->stFileHandle.dwCurrentOffset =0; // 만약 추가 옵션(a)이 설정되어 있으면 파일의 끝으로 이동 if(pcMode[0]=='a') { kSeekFile(pstFile,0,FILESYSTEM_SEEK_END); } // 동기화 kUnlock(&(gs_stFileSystemManager.stMutex)); return pstFile; }
/** * 윈도우 프레임을 그림 */ void kDrawWindowFrame( int iX, int iY, int iWidth, int iHeight, const char* pcTitle ) { char* pcTestString1 = "This is MINT64 OS's window prototype~!!!"; char* pcTestString2 = "Coming soon~!!!"; // 윈도우 프레임의 가장자리를 그림, 2 픽셀 두께 kDrawRect( iX, iY, iX + iWidth, iY + iHeight, RGB( 50,50,50 ), FALSE ); kDrawRect( iX + 1, iY + 1, iX + iWidth - 1, iY + iHeight - 1, RGB( 50,50,50 ), FALSE ); // 제목 표시줄을 채움 kDrawRect( iX, iY + 3, iX + iWidth - 1, iY + 21, RGB( 100, 100, 100 ), TRUE ); // 윈도우 제목을 표시 kDrawText( iX + 6, iY + 3, RGB( 50, 50, 255 ), RGB( 100, 100, 100 ), pcTitle, kStrLen( pcTitle ) ); // 제목 표시줄을 입체로 보이게 위쪽의 선을 그림, 2 픽셀 두께 kDrawLine( iX + 1, iY + 1, iX + iWidth - 1, iY + 1, RGB( 50,50,50 ) ); kDrawLine( iX + 1, iY + 2, iX + iWidth - 1, iY + 2, RGB( 50,50,50 ) ); kDrawLine( iX + 1, iY + 2, iX + 1, iY + 20, RGB( 50,50,50 ) ); kDrawLine( iX + 2, iY + 2, iX + 2, iY + 20, RGB( 50,50,50 ) ); // 제목 표시줄의 아래쪽에 선을 그림 kDrawLine( iX + 2, iY + 19, iX + iWidth - 2, iY + 19, RGB( 46, 59, 30 ) ); kDrawLine( iX + 2, iY + 20, iX + iWidth - 2, iY + 20, RGB( 46, 59, 30 ) ); // 닫기 버튼을 그림, 오른쪽 상단에 표시 kDrawRect( iX + iWidth - 2 - 18, iY + 1, iX + iWidth - 2, iY + 19, RGB( 255, 255, 255 ), TRUE ); // 닫기 버튼을 입체로 보이게 선을 그림, 2 픽셀 두께로 그림 kDrawRect( iX + iWidth - 2, iY + 1, iX + iWidth - 2, iY + 19 - 1, RGB( 86, 86, 86 ), TRUE ); kDrawRect( iX + iWidth - 2 - 1, iY + 1, iX + iWidth - 2 - 1, iY + 19 - 1, RGB( 86, 86, 86 ), TRUE ); kDrawRect( iX + iWidth - 2 - 18 + 1, iY + 19, iX + iWidth - 2, iY + 19, RGB( 86, 86, 86 ), TRUE ); kDrawRect( iX + iWidth - 2 - 18 + 1, iY + 19 - 1, iX + iWidth - 2, iY + 19 - 1, RGB( 86, 86, 86 ), TRUE ); kDrawLine( iX + iWidth - 2 - 18, iY + 1, iX + iWidth - 2 - 1, iY + 1, RGB( 229, 229, 229 ) ); kDrawLine( iX + iWidth - 2 - 18, iY + 1 + 1, iX + iWidth - 2 - 2, iY + 1 + 1, RGB( 229, 229, 229 ) ); kDrawLine( iX + iWidth - 2 - 18, iY + 1, iX + iWidth - 2 - 18, iY + 19, RGB( 229, 229, 229 ) ); kDrawLine( iX + iWidth - 2 - 18 + 1, iY + 1, iX + iWidth - 2 - 18 + 1, iY + 19 - 1, RGB( 229, 229, 229 ) ); // 대각선 X를 그림, 3 픽셀로 그림 kDrawLine( iX + iWidth - 2 - 18 + 4, iY + 1 + 4, iX + iWidth - 2 - 4, iY + 19 - 4, RGB( 50, 50, 255 ) ); kDrawLine( iX + iWidth - 2 - 18 + 5, iY + 1 + 4, iX + iWidth - 2 - 4, iY + 19 - 5, RGB( 50, 50, 255 ) ); kDrawLine( iX + iWidth - 2 - 18 + 4, iY + 1 + 5, iX + iWidth - 2 - 5, iY + 19 - 4, RGB( 50, 50, 255 ) ); kDrawLine( iX + iWidth - 2 - 18 + 4, iY + 19 - 4, iX + iWidth - 2 - 4, iY + 1 + 4, RGB( 50,50,255 ) ); kDrawLine( iX + iWidth - 2 - 18 + 5, iY + 19 - 4, iX + iWidth - 2 - 4, iY + 1 + 5, RGB( 50,50,255 ) ); kDrawLine( iX + iWidth - 2 - 18 + 4, iY + 19 - 5, iX + iWidth - 2 - 5, iY + 1 + 4, RGB( 50,50,255 ) ); // 내부를 그림 kDrawRect( iX + 2, iY + 21, iX + iWidth - 2, iY + iHeight - 2, RGB( 0, 0, 0 ), TRUE ); // 테스트 문자 출력 kDrawText( iX + 10, iY + 30, RGB( 50, 50, 255 ), RGB( 0, 0, 0 ), pcTestString1, kStrLen( pcTestString1 ) ); kDrawText( iX + 10, iY + 50, RGB(50, 50, 255 ), RGB( 0, 0, 0 ), pcTestString2, kStrLen( pcTestString2 ) ); }
/** * MP 설정 테이블을 분석해서 필요한 정보를 저장하는 함수 */ BOOL kAnalysisMPConfigurationTable( void ) { QWORD qwMPFloatingPointerAddress; MPFLOATINGPOINTER* pstMPFloatingPointer; MPCONFIGURATIONTABLEHEADER* pstMPConfigurationHeader; BYTE bEntryType; WORD i; QWORD qwEntryAddress; PROCESSORENTRY* pstProcessorEntry; BUSENTRY* pstBusEntry; // 자료구조 초기화 kMemSet( &gs_stMPConfigurationManager, 0, sizeof( MPCONFIGRUATIONMANAGER ) ); gs_stMPConfigurationManager.bISABusID = 0xFF; // MP 플로팅 포인터의 어드레스를 구함 if( kFindMPFloatingPointerAddress( &qwMPFloatingPointerAddress ) == FALSE ) { return FALSE; } // MP 플로팅 테이블 설정 pstMPFloatingPointer = ( MPFLOATINGPOINTER* ) qwMPFloatingPointerAddress; gs_stMPConfigurationManager.pstMPFloatingPointer = pstMPFloatingPointer; pstMPConfigurationHeader = ( MPCONFIGURATIONTABLEHEADER* ) ( ( QWORD ) pstMPFloatingPointer->dwMPConfigurationTableAddress & 0xFFFFFFFF ); // PIC 모드 지원 여부 저장 if( pstMPFloatingPointer->vbMPFeatureByte[ 1 ] & MP_FLOATINGPOINTER_FEATUREBYTE2_PICMODE ) { gs_stMPConfigurationManager.bUsePICMode = TRUE; } // MP 설정 테이블 헤더와 기본 MP 설정 테이블 엔트리의 시작 어드레스 설정 gs_stMPConfigurationManager.pstMPConfigurationTableHeader = pstMPConfigurationHeader; gs_stMPConfigurationManager.qwBaseEntryStartAddress = pstMPFloatingPointer->dwMPConfigurationTableAddress + sizeof( MPCONFIGURATIONTABLEHEADER ); // 모든 엔트리를 돌면서 프로세서의 코어 수를 계산하고 ISA 버스를 검색하여 ID를 저장 qwEntryAddress = gs_stMPConfigurationManager.qwBaseEntryStartAddress; for( i = 0 ; i < pstMPConfigurationHeader->wEntryCount ; i++ ) { bEntryType = *( BYTE* ) qwEntryAddress; switch( bEntryType ) { // 프로세서 엔트리이면 프로세서의 수를 하나 증가시킴 case MP_ENTRYTYPE_PROCESSOR: pstProcessorEntry = ( PROCESSORENTRY* ) qwEntryAddress; if( pstProcessorEntry->bCPUFlags & MP_PROCESSOR_CPUFLAGS_ENABLE ) { gs_stMPConfigurationManager.iProcessorCount++; } qwEntryAddress += sizeof( PROCESSORENTRY ); break; // 버스 엔트리이면 ISA 버스인지 확인하여 저장 case MP_ENTRYTYPE_BUS: pstBusEntry = ( BUSENTRY* ) qwEntryAddress; if( kMemCmp( pstBusEntry->vcBusTypeString, MP_BUS_TYPESTRING_ISA, kStrLen( MP_BUS_TYPESTRING_ISA ) ) == 0 ) { gs_stMPConfigurationManager.bISABusID = pstBusEntry->bBusID; } qwEntryAddress += sizeof( BUSENTRY ); break; // 기타 엔트리는 무시하고 이동 case MP_ENTRYTYPE_IOAPIC: case MP_ENTRYTYPE_IOINTERRUPTASSIGNMENT: case MP_ENTRYTYPE_LOCALINTERRUPTASSIGNMENT: default: qwEntryAddress += 8; break; } } return TRUE; }
/** * 메모리 정보를 출력 */ static void kDrawMemoryInformation( QWORD qwWindowID, int iY, int iWindowWidth ) { char vcBuffer[ 100 ]; QWORD qwTotalRAMKbyteSize; QWORD qwDynamicMemoryStartAddress; QWORD qwDynamicMemoryUsedSize; QWORD qwUsedPercent; QWORD qwTemp; int iUsageBarWidth; RECT stArea; int iMiddleX; // Mbyte 단위의 메모리를 Kbyte 단위로 변환 qwTotalRAMKbyteSize = kGetTotalRAMSize() * 1024; // 메모리 정보를 표시 kSPrintf( vcBuffer, "Total Size: %d KB ", qwTotalRAMKbyteSize ); kDrawText( qwWindowID, SYSTEMMONITOR_PROCESSOR_MARGIN + 10, iY + 3, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcBuffer, kStrLen( vcBuffer ) ); // 동적 메모리의 정보를 반환 kGetDynamicMemoryInformation( &qwDynamicMemoryStartAddress, &qwTemp, &qwTemp, &qwDynamicMemoryUsedSize ); kSPrintf( vcBuffer, "Used Size: %d KB ", ( qwDynamicMemoryUsedSize + qwDynamicMemoryStartAddress ) / 1024 ); kDrawText( qwWindowID, SYSTEMMONITOR_PROCESSOR_MARGIN + 10, iY + 21, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcBuffer, kStrLen( vcBuffer ) ); //-------------------------------------------------------------------------- // 메모리 사용량을 나타내는 막대를 표시 //-------------------------------------------------------------------------- // 메모리 사용량을 표시하는 막대의 전체에 테두리를 표시 kDrawRect( qwWindowID, SYSTEMMONITOR_PROCESSOR_MARGIN, iY + 40, iWindowWidth - SYSTEMMONITOR_PROCESSOR_MARGIN, iY + SYSTEMMONITOR_MEMORY_HEIGHT - 32, RGB( 0, 0, 0 ), FALSE ); // 메모리 사용량(%)을 계산 qwUsedPercent = ( qwDynamicMemoryStartAddress + qwDynamicMemoryUsedSize ) * 100 / 1024 / qwTotalRAMKbyteSize; if( qwUsedPercent > 100 ) { qwUsedPercent = 100; } // 메모리 사용량을 나타내는 막대의 길이, ( 막대 전체의 길이 * 메모리 사용량 / 100 ) iUsageBarWidth = ( iWindowWidth - 2 * SYSTEMMONITOR_PROCESSOR_MARGIN ) * qwUsedPercent / 100; // 메모리 사용량을 표시하는 영역의 막대 내부를 표시 // 색칠된 막대를 표시, 테두리와 2픽셀 정도 여유 공간을 둠 kDrawRect( qwWindowID, SYSTEMMONITOR_PROCESSOR_MARGIN + 2, iY + 42, SYSTEMMONITOR_PROCESSOR_MARGIN + 2 + iUsageBarWidth, iY + SYSTEMMONITOR_MEMORY_HEIGHT - 34, SYSTEMMONITOR_BAR_COLOR, TRUE ); // 빈 막대를 표시, 테두리와 2픽셀 정도 여유 공간을 둠 kDrawRect( qwWindowID, SYSTEMMONITOR_PROCESSOR_MARGIN + 2 + iUsageBarWidth, iY + 42, iWindowWidth - SYSTEMMONITOR_PROCESSOR_MARGIN - 2, iY + SYSTEMMONITOR_MEMORY_HEIGHT - 34, WINDOW_COLOR_BACKGROUND, TRUE ); // 사용량을 나타내는 텍스트 표시, 막대의 가운데에 사용량이 표시되도록 함 kSPrintf( vcBuffer, "Usage: %d%%", qwUsedPercent ); iMiddleX = ( iWindowWidth - ( kStrLen( vcBuffer ) * FONT_ENGLISHWIDTH ) ) / 2; kDrawText( qwWindowID, iMiddleX, iY + 45, RGB( 0, 0, 0 ), WINDOW_COLOR_BACKGROUND, vcBuffer, kStrLen( vcBuffer ) ); // 메모리 정보가 표시된 영역만 화면에 다시 업데이트 kSetRectangleData(0, iY, iWindowWidth, iY + SYSTEMMONITOR_MEMORY_HEIGHT, &stArea ); kUpdateScreenByWindowArea( qwWindowID, &stArea ); }
/** * 그래픽 모드를 테스트하는 함수 */ void kStartGraphicModeTest() { VBEMODEINFOBLOCK* pstVBEMode; int iX1, iY1, iX2, iY2; COLOR stColor1, stColor2; int i; char* vpcString[] = { "Pixel", "Line", "Rectangle", "Circle", "MINT64 OS~!!!" }; //========================================================================== // 점, 선, 사각형, 원, 그리고 문자를 간단히 출력 //========================================================================== // (0, 0)에 Pixel이란 문자열을 검은색 바탕에 흰색으로 출력 kDrawText( 0, 0, RGB( 255, 255, 255), RGB( 0, 0, 0 ), vpcString[ 0 ], kStrLen( vpcString[ 0 ] ) ); // 픽셀을 (1, 20), (2, 20)에 흰색으로 출력 kDrawPixel( 1, 20, RGB( 255, 255, 255 ) ); kDrawPixel( 2, 20, RGB( 255, 255, 255 ) ); // (0, 25)에 Line이란 문자열을 검은색 바탕에 빨간색으로 출력 kDrawText( 0, 25, RGB( 255, 0, 0), RGB( 0, 0, 0 ), vpcString[ 1 ], kStrLen( vpcString[ 1 ] ) ); // (20, 50)을 중심으로 (1000, 50) (1000, 100), (1000, 150), (1000, 200), // (1000, 250)까지 빨간색으로 출력 kDrawLine( 20, 50, 1000, 50, RGB( 255, 0, 0 ) ); kDrawLine( 20, 50, 1000, 100, RGB( 255, 0, 0 ) ); kDrawLine( 20, 50, 1000, 150, RGB( 255, 0, 0 ) ); kDrawLine( 20, 50, 1000, 200, RGB( 255, 0, 0 ) ); kDrawLine( 20, 50, 1000, 250, RGB( 255, 0, 0 ) ); // (0, 180)에 Rectangle이란 문자열을 검은색 바탕에 녹색으로 출력 kDrawText( 0, 180, RGB( 0, 255, 0), RGB( 0, 0, 0 ), vpcString[ 2 ], kStrLen( vpcString[ 2 ] ) ); // (20, 200)에서 시작하여 길이가 각각 50, 100, 150, 200인 사각형을 녹색으로 출력 kDrawRect( 20, 200, 70, 250, RGB( 0, 255, 0 ), FALSE ); kDrawRect( 120, 200, 220, 300, RGB( 0, 255, 0 ), TRUE ); kDrawRect( 270, 200, 420, 350, RGB( 0, 255, 0 ), FALSE ); kDrawRect( 470, 200, 670, 400, RGB( 0, 255, 0 ), TRUE ); // (0, 550)에 Circle이란 문자열을 검은색 바탕에 파란색으로 출력 kDrawText( 0, 550, RGB( 0, 0, 255), RGB( 0, 0, 0 ), vpcString[ 3 ], kStrLen( vpcString[ 3 ] ) ); // (45, 600)에서 시작하여 반지름이 25, 50, 75, 100인 원을 파란색으로 출력 kDrawCircle( 45, 600, 25, RGB( 0, 0, 255 ), FALSE ) ; kDrawCircle( 170, 600, 50, RGB( 0, 0, 255 ), TRUE ) ; kDrawCircle( 345, 600, 75, RGB( 0, 0, 255 ), FALSE ) ; kDrawCircle( 570, 600, 100, RGB( 0, 0, 255 ), TRUE ) ; // 키 입력 대기 kGetCh(); //========================================================================== // 점, 선, 사각형, 원, 그리고 문자를 무작위로 출력 //========================================================================== // q 키가 입력될 때까지 아래를 반복 do { // 점 그리기 for( i = 0 ; i < 100 ; i++ ) { // 임의의 X좌표와 색을 반환 kGetRandomXY( &iX1, &iY1 ); stColor1 = kGetRandomColor(); // 점 그리기 kDrawPixel( iX1, iY1, stColor1 ); } // 선 그리기 for( i = 0 ; i < 100 ; i++ ) { // 임의의 X좌표와 색을 반환 kGetRandomXY( &iX1, &iY1 ); kGetRandomXY( &iX2, &iY2 ); stColor1 = kGetRandomColor(); // 선 그리기 kDrawLine( iX1, iY1, iX2, iY2, stColor1 ); } // 사각형 그리기 for( i = 0 ; i < 20 ; i++ ) { // 임의의 X좌표와 색을 반환 kGetRandomXY( &iX1, &iY1 ); kGetRandomXY( &iX2, &iY2 ); stColor1 = kGetRandomColor(); // 사각형 그리기 kDrawRect( iX1, iY1, iX2, iY2, stColor1, kRandom() % 2 ); } // 원 그리기 for( i = 0 ; i < 100 ; i++ ) { // 임의의 X좌표와 색을 반환 kGetRandomXY( &iX1, &iY1 ); stColor1 = kGetRandomColor(); // 원 그리기 kDrawCircle( iX1, iY1, ABS( kRandom() % 50 + 1 ), stColor1, kRandom() % 2 ); } // 텍스트 표시 for( i = 0 ; i < 100 ; i++ ) { // 임의의 X좌표와 색을 반환 kGetRandomXY( &iX1, &iY1 ); stColor1 = kGetRandomColor(); stColor2 = kGetRandomColor(); // 텍스트 출력 kDrawText( iX1, iY1, stColor1, stColor2, vpcString[ 4 ], kStrLen( vpcString[ 4 ] ) ); } } while( kGetCh() != 'q' ); //========================================================================== // 윈도우 프로토타입을 출력 //========================================================================== // q 키를 눌러서 빠져 나왔다면 윈도우 프로토타입을 표시함 while( 1 ) { // 배경을 출력 kDrawRect(0, 0, 1024, 768, RGB( 232, 255, 232 ), TRUE ); // 윈도우 프레임을 3개 그림 for( i = 0 ; i < 3 ; i++ ) { kGetRandomXY( &iX1, &iY1 ); kDrawWindowFrame( iX1, iY1, 400, 200, "MINT64 OS Test Window" ); } kGetCh(); } }
/** * 파라미터 자료구조를 초기화 */ void kInitializeParameter( PARAMETERLIST* pstList, const char* pcParameter ) { pstList->pcBuffer = pcParameter; pstList->iLength = kStrLen( pcParameter ); pstList->iCurrentPosition = 0; }
/** * 윈도우 매니저 태스크 */ void kStartWindowManager( void ) { int iMouseX, iMouseY; BOOL bMouseDataResult; BOOL bKeyDataResult; BOOL bEventQueueResult; //------------------------------------------------------------------------- QWORD qwLastTickCount; QWORD qwPreviousLoopExecutionCount; QWORD qwLoopExecutionCount; QWORD qwMinLoopExecutionCount; char vcTemp[ 40 ]; RECT stLoopCountArea; QWORD qwBackgroundWindowID; //------------------------------------------------------------------------- // GUI 시스템을 초기화 kInitializeGUISystem(); // 현재 마우스 위치에 커서를 출력 kGetCursorPosition( &iMouseX, &iMouseY ); kMoveCursor( iMouseX, iMouseY ); //------------------------------------------------------------------------- // 루프 수행 횟수 측정용 변수 초기화 qwLastTickCount = kGetTickCount(); qwPreviousLoopExecutionCount = 0; qwLoopExecutionCount = 0; qwMinLoopExecutionCount = 0xFFFFFFFFFFFFFFFF; qwBackgroundWindowID = kGetBackgroundWindowID(); //------------------------------------------------------------------------- // 윈도우 매니저 태스크 루프 while( 1 ) { //------------------------------------------------------------------------- // 1초마다 윈도우 매니저 태스크 루프를 수행한 횟수를 측정하여 최솟값을 기록 if( kGetTickCount() - qwLastTickCount > 1000 ) { qwLastTickCount = kGetTickCount(); // 1초 전에 수행한 태스크 루프의 수와 현재 태스크 루프의 수를 빼서 // 최소 루프 수행 횟수와 비교하여 최소 루프 수행 횟수를 업데이트 if( ( qwLoopExecutionCount - qwPreviousLoopExecutionCount ) < qwMinLoopExecutionCount ) { qwMinLoopExecutionCount = qwLoopExecutionCount - qwPreviousLoopExecutionCount; } qwPreviousLoopExecutionCount = qwLoopExecutionCount; // 루프의 최소 수행 횟수를 1초마다 업데이트 kSPrintf( vcTemp, "MIN Loop Execution Count:%d ", qwMinLoopExecutionCount ); kDrawText( qwBackgroundWindowID, 0, 0, RGB( 0, 0, 0 ), RGB( 255, 255, 255 ), vcTemp, kStrLen( vcTemp ) ); // 배경 윈도우 전체를 업데이트하면 시간이 많이 걸리므로 배경 윈도우에 // 루프 수행 횟수가 출력된 부분만 업데이트 kSetRectangleData( 0, 0, kStrLen( vcTemp ) * FONT_ENGLISHWIDTH, FONT_ENGLISHHEIGHT, &stLoopCountArea ); kRedrawWindowByArea( &stLoopCountArea, qwBackgroundWindowID ); } qwLoopExecutionCount++; //------------------------------------------------------------------------- // 마우스 데이터를 처리 bMouseDataResult = kProcessMouseData(); // 키 데이터를 처리 bKeyDataResult = kProcessKeyData(); // 윈도우 매니저의 이벤트 큐에 수신된 데이터를 처리. 수신된 모든 이벤트를 처리함 bEventQueueResult = FALSE; while( kProcessEventQueueData() == TRUE ) { bEventQueueResult = TRUE; } // 처리한 데이터가 하나도 없다면 Sleep()을 수행하여 프로세서를 양보함 if( ( bMouseDataResult == FALSE ) && ( bKeyDataResult == FALSE ) && ( bEventQueueResult == FALSE ) ) { kSleep( 0 ); } } }
/** * 현재 생성된 모든 태스크의 정보를 출력 */ static void kShowTaskList( const char* pcParameterBuffer ) { int i; TCB* pstTCB; int iCount = 0; int iTotalTaskCount = 0; char vcBuffer[ 20 ]; int iRemainLength; int iProcessorCount; // 코어 수만큼 루프를 돌면서 각 스케줄러에 있는 태스크의 수를 더함 iProcessorCount = kGetProcessorCount(); for( i = 0 ; i < iProcessorCount ; i++ ) { iTotalTaskCount += kGetTaskCount( i ); } kPrintf( "================= Task Total Count [%d] =================\n", iTotalTaskCount ); // 코어가 2개 이상이면 각 스케줄러 별로 개수를 출력 if( iProcessorCount > 1 ) { // 각 스케줄러 별로 태스크의 개수를 출력 for( i = 0 ; i < iProcessorCount ; i++ ) { if( ( i != 0 ) && ( ( i % 4 ) == 0 ) ) { kPrintf( "\n" ); } kSPrintf( vcBuffer, "Core %d : %d", i, kGetTaskCount( i ) ); kPrintf( vcBuffer ); // 출력하고 남은 공간을 모두 스페이스바로 채움 iRemainLength = 19 - kStrLen( vcBuffer ); kMemSet( vcBuffer, ' ', iRemainLength ); vcBuffer[ iRemainLength ] = '\0'; kPrintf( vcBuffer ); } kPrintf( "\nPress any key to continue... ('q' is exit) : " ); if( kGetCh() == 'q' ) { kPrintf( "\n" ); return ; } kPrintf( "\n\n" ); } for( i = 0 ; i < TASK_MAXCOUNT ; i++ ) { // TCB를 구해서 TCB가 사용 중이면 ID를 출력 pstTCB = kGetTCBInTCBPool( i ); if( ( pstTCB->stLink.qwID >> 32 ) != 0 ) { // 태스크가 6개 출력될 때마다, 계속 태스크 정보를 표시할지 여부를 확인 if( ( iCount != 0 ) && ( ( iCount % 6 ) == 0 ) ) { kPrintf( "Press any key to continue... ('q' is exit) : " ); if( kGetCh() == 'q' ) { kPrintf( "\n" ); break; } kPrintf( "\n" ); } kPrintf( "[%d] Task ID[0x%Q], Priority[%d], Flags[0x%Q], Thread[%d]\n", 1 + iCount++, pstTCB->stLink.qwID, GETPRIORITY( pstTCB->qwFlags ), pstTCB->qwFlags, kGetListCount( &( pstTCB->stChildThreadList ) ) ); kPrintf( " Core ID[0x%X] CPU Affinity[0x%X]\n", pstTCB->bAPICID, pstTCB->bAffinity ); kPrintf( " Parent PID[0x%Q], Memory Address[0x%Q], Size[0x%Q]\n", pstTCB->qwParentProcessID, pstTCB->pvMemoryAddress, pstTCB->qwMemorySize ); } } }
/** * 윈도우 프레임을 그림 */ void kDrawWindowFrame( int iX, int iY, int iWidth, int iHeight, const char* pcTitle ) { char* pcTestString1 = "This is MINT64 OS's window prototype~!!!"; char* pcTestString2 = "Coming soon~!!!"; VBEMODEINFOBLOCK* pstVBEMode; COLOR* pstVideoMemory; RECT stScreenArea; // VBE 모드 정보 블록을 반환 pstVBEMode = kGetVBEModeInfoBlock(); // 화면 영역 설정 stScreenArea.iX1 = 0; stScreenArea.iY1 = 0; stScreenArea.iX2 = pstVBEMode->wXResolution - 1; stScreenArea.iY2 = pstVBEMode->wYResolution - 1; // 그래픽 메모리 어드레스 설정 pstVideoMemory = ( COLOR* ) ( ( QWORD )pstVBEMode->dwPhysicalBasePointer & 0xFFFFFFFF ); // 윈도우 프레임의 가장자리를 그림, 2 픽셀 두께 kInternalDrawRect( &stScreenArea, pstVideoMemory, iX, iY, iX + iWidth, iY + iHeight, RGB( 109, 218, 22 ), FALSE ); kInternalDrawRect( &stScreenArea, pstVideoMemory, iX + 1, iY + 1, iX + iWidth - 1, iY + iHeight - 1, RGB( 109, 218, 22 ), FALSE ); // 제목 표시줄을 채움 kInternalDrawRect( &stScreenArea, pstVideoMemory, iX, iY + 3, iX + iWidth - 1, iY + 21, RGB( 79, 204, 11 ), TRUE ); // 윈도우 제목을 표시 kInternalDrawText( &stScreenArea, pstVideoMemory, iX + 6, iY + 3, RGB( 255, 255, 255 ), RGB( 79, 204, 11 ), pcTitle, kStrLen( pcTitle ) ); // 제목 표시줄을 입체로 보이게 위쪽의 선을 그림, 2 픽셀 두께 kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + 1, iY + 1, iX + iWidth - 1, iY + 1, RGB( 183, 249, 171 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + 1, iY + 2, iX + iWidth - 1, iY + 2, RGB( 150, 210, 140 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + 1, iY + 2, iX + 1, iY + 20, RGB( 183, 249, 171 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + 2, iY + 2, iX + 2, iY + 20, RGB( 150, 210, 140 ) ); // 제목 표시줄의 아래쪽에 선을 그림 kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + 2, iY + 19, iX + iWidth - 2, iY + 19, RGB( 46, 59, 30 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + 2, iY + 20, iX + iWidth - 2, iY + 20, RGB( 46, 59, 30 ) ); // 닫기 버튼을 그림, 오른쪽 상단에 표시 kInternalDrawRect( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18, iY + 1, iX + iWidth - 2, iY + 19, RGB( 255, 255, 255 ), TRUE ); // 닫기 버튼을 입체로 보이게 선을 그림, 2 픽셀 두께로 그림 kInternalDrawRect( &stScreenArea, pstVideoMemory, iX + iWidth - 2, iY + 1, iX + iWidth - 2, iY + 19 - 1, RGB( 86, 86, 86 ), TRUE ); kInternalDrawRect( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 1, iY + 1, iX + iWidth - 2 - 1, iY + 19 - 1, RGB( 86, 86, 86 ), TRUE ); kInternalDrawRect( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 1, iY + 19, iX + iWidth - 2, iY + 19, RGB( 86, 86, 86 ), TRUE ); kInternalDrawRect( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 1, iY + 19 - 1, iX + iWidth - 2, iY + 19 - 1, RGB( 86, 86, 86 ), TRUE ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18, iY + 1, iX + iWidth - 2 - 1, iY + 1, RGB( 229, 229, 229 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18, iY + 1 + 1, iX + iWidth - 2 - 2, iY + 1 + 1, RGB( 229, 229, 229 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18, iY + 1, iX + iWidth - 2 - 18, iY + 19, RGB( 229, 229, 229 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 1, iY + 1, iX + iWidth - 2 - 18 + 1, iY + 19 - 1, RGB( 229, 229, 229 ) ); // 대각선 X를 그림, 3 픽셀로 그림 kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 4, iY + 1 + 4, iX + iWidth - 2 - 4, iY + 19 - 4, RGB( 71, 199, 21 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 5, iY + 1 + 4, iX + iWidth - 2 - 4, iY + 19 - 5, RGB( 71, 199, 21 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 4, iY + 1 + 5, iX + iWidth - 2 - 5, iY + 19 - 4, RGB( 71, 199, 21 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 4, iY + 19 - 4, iX + iWidth - 2 - 4, iY + 1 + 4, RGB( 71, 199, 21 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 5, iY + 19 - 4, iX + iWidth - 2 - 4, iY + 1 + 5, RGB( 71, 199, 21 ) ); kInternalDrawLine( &stScreenArea, pstVideoMemory, iX + iWidth - 2 - 18 + 4, iY + 19 - 5, iX + iWidth - 2 - 5, iY + 1 + 4, RGB( 71, 199, 21 ) ); // 내부를 그림 kInternalDrawRect( &stScreenArea, pstVideoMemory, iX + 2, iY + 21, iX + iWidth - 2, iY + iHeight - 2, RGB( 255, 255, 255 ), TRUE ); // 테스트 문자 출력 kInternalDrawText( &stScreenArea, pstVideoMemory, iX + 10, iY + 30, RGB( 0, 0, 0 ), RGB( 255, 255, 255 ), pcTestString1, kStrLen( pcTestString1 ) ); kInternalDrawText( &stScreenArea, pstVideoMemory, iX + 10, iY + 50, RGB( 0, 0, 0 ), RGB( 255, 255, 255 ), pcTestString2, kStrLen( pcTestString2 ) ); }