2012년1월16일_원라인에디터프로젝트_보고서_1단계...창 만들기



image

상기와 같이 UI를 만들어야 한다. 그다지 어렵지 않은데? 사실 뒷부분도 그리 어렵지 않다.
보고서를 매일매일 써야하는데 갑자기 급귀차니즘병에 걸려 거의 세 달? 두 달이상을 쉬었다. 그래서 수료하기 전까지 좀 고생할듯..

일단 실행 후 보고서이고 오래된거니 소스코드를 올리고 설명하는 것으로 마쳐야겠당. 기억나는 부분만 적고~



1일차…PutChar( )의 제작과 테스트


2011년 10월 11일...CM샘께서 원라인에디터 검사한다고 하셔서 억지로 시작~

● main.c

   1: include "UserDef.h"
   2:  
   3: int main()
   4: {
   5:     char ch = 'A';
   6:  
   7:     system("cls");
   8:     PutChar(10, 10, ch);
   9:     PutChar(10, 15, ch);
  10:  
  11:     getch();
  12:     return 0;
  13: }



● UserDef.c

   1: #include "UserDef.h"
   2:  
   3: /*********************************************************************
   4:     기  능: 화면에 한 문자를 출력하는 함수
   5:     설  명: RAM -> VideoRAM 전달 되는 영역에 문자를 출력.
   6:     인  자:    1. x축 시작좌표
   7:             2. y축 시작좌표
   8:             3. 출력될 문자
   9: *********************************************************************/
  10: void PutChar(unsigned char x, unsigned char y, unsigned char ucData)
  11: {
  12:     char far *location;
  13:     char attr = 7;
  14:     
  15:     location = (char far *)0xb8000000 + y * 160 + x * 2;
  16:     *location++ = ucData;
  17:     *location = attr;
  18:  
  19:     return ;
  20: }


<소스설명>

image

RAM의 0xB8000000번지부터 0xB000FFFF번지까지 화면에 표시할 데이터를 넣으면 그래픽카드의 VRAM에 전달되 모니터에 뿌려준다.
이건 옛날 컴퓨터부터 지금 생산되고 있는 컴퓨터까지 모두 공통이므로 어디서든 테스트할 수 있다.
대신 TurboC라는 16비트(?) 컴파일러를 써야한다고 하는데 왜 그런지 모른다. 누가 알려줘~
그래서 PutChar( )를 보면,

char형 포인터인데 far키워드를 중간에 넣어 16비트 어드레스만 사용하지 않고 32비트 어드레스를 사용할 수 있게 한다.
(실제 8086은 20비트 어드레스버스, 80286은 24비트 어드레스버스를 가진다. Offset레지스터를 사용해 주소지정하는 방식.)
자세한 설명은 이 블로그를 참조하세요. http://blog.naver.com/bravedog/100005576789

메모리를 1Byte단위로 볼 수 있는 far포인터를 선언하고 아래 attr(속성)은 7로 한다.
속성값 7은 2진수로 보면 0000 0111이므로 상위 4비트는 배경색검은색이고 하위 4비트 중 0~2번째 비트가 모두 1로 흰색이다.
자세한건 여기에 값을 넣어서 글자색깔과 배경색을 관찰하면 금방 알 수 있다.

  15:     location = (char far *)0xb8000000 + y * 160 + x * 2;

비디오메모리 시작주소(RAM영역) 0xB8000000부터,
y는 행으로 80열이고 각 2Bytes이니 160을 곱해주고, x값은 열로 글자 한칸이 2Bytes(ASCII와 속성)를 차지하므로 2를 곱해준다.

  16:     *location++ = ucData;

16행을 보면 좀 헤깔리게 코딩하였는데 location에 ucData의 값이 먼저 되입되고 후에 location이 가리키는 주소값이 1증가한다.
한 줄로 쓰지 말고 아래와 같이,

    *location = ucData;
    ++location;

이렇게 두 줄로 쓰면 코드를 더 빠르고 쉽게 이해할 수 있다.

main.c에선,

   8:     PutChar(10, 10, ch);
   9:     PutChar(10, 15, ch);

단순히 (10,10)과 (10,15)에 같은 글자 ‘A’를 화면에 출력하고 있다.



● 컴파일

image


● 실행결과

image 


실행을 윈도우xp의 cmd창에서 하지 않고 DOSBox라는 진짜 옛날 DOS에뮬레이터로 하고 있다.
DOSBox는 VMware와 비슷하게 가상머신이라고 할 수 있는데 보다 완벽한 DOS환경을 갖추고 있다.
(cmd는 DOS가 아니다.)
암튼 DOSBox로 TurboC 어플리케이션을 개발하면 좀 더 빠른속도로 좀 더 안정적인 결과를 얻을 수 있다.





2일차…PrintRect( )의 제작 시작!!



2011년 10월 12일...
PutChar( )는 화면에 하나의 문자만 표시하는 함수로 이 함수를 사용해 문자열을 출력하거나 테두리를 그릴 수 있다.
그러나 PutChar( )를 여러 번 호출해 테두리를 그리면 노가다 프로그래밍이 되어 버리니..
PutChar( )를 이용하여 테두리(박스)만 전문적으로 그리는 함수를 만들어 보자. 사각형 박스니 Rectangle이다 줄여서 Rect!!
화면에 출력하니 Print을 붙여 PrintRect라고 함수의 이름을 지었다.


● main.c

   1: #include "UserDef.h"
   2:  
   3: int main()
   4: {
   5:     system("cls");
   6:     PutChar(10, 10, PEN_SERO);
   7:     PutChar(10, 15, PEN_GARO);
   8:     PrintRect(0,0,30,30);
   9:  
  10:     getch();
  11:     return 0;
  12: }


● UserDef.c

   1: #include "UserDef.h"
   2:  
   3: /*********************************************************************
   4:     기  능: 화면에 한 문자를 출력하는 함수
   5:     설  명: RAM -> VideoRAM 전달 되는 영역에 문자를 출력.
   6:     인  자:    1. ucX축 시작좌표
   7:             2. ucY축 시작좌표
   8:             3. 출력될 문자
   9: *********************************************************************/
  10: void PutChar(unsigned char ucX, unsigned char ucY, unsigned char ucData)
  11: {
  12:     char far *location;
  13:     char attr = 7;
  14:     
  15:     location = (char far *)0Xb8000000 + ucY * 160 + ucX * 2;
  16:     *location++ = ucData;
  17:     *location = attr;
  18:  
  19:     return ;
  20: }
  21:  
  22: /*********************************************************************
  23:     기  능: 화면에 사각형박스를 그리는 함수
  24:     설  명: PutChar()를 사용.
  25:     인  자:    1. X축 시작좌표
  26:             2. Y축 시작좌표
  27:             3. 박스의 폭
  28:             4. 박스의 높이
  29: *********************************************************************/
  30: void PrintRect(unsigned char ucX, unsigned char ucY, 
  31:                 unsigned char width, unsigned char height) 
  32: {
  33:     unsigned char ucRow;
  34:     unsigned char ucCol;
  35:     
  36:     PutChar(ucX, ucY, PEN_LT);
  37:     for(++ucX ; ucX < width - 1 ; ++ucX)
  38:     {
  39:         PutChar(ucX, ucY, PEN_GARO);
  40:     }
  41:  
  42:     return ;
  43: }


PrintRect( )를 호출하며 인자로 0, 0, 30, 30을 넘겨주었다.
뜻은 (0, 0)부터 가로30칸 세로30칸의 크기로 사각형을 그리라는 건데..그 날 무슨 일로 바빴는지 북쪽(상단)만 완성이 되어있다.
그리고 DOS창은 80x25니 30을 넘겨주면 안 되지~


● 실행결과

image 

마지막에 꺽여야 하는데 이 날은 구현하지 못 하였다. 왜 그랬을까?



 

3일차…PrintRect( )의 구현



2011년 10월 13일...PutChar( )을 반복호출해 쉽게 큰 단위의 사각형을 만들자.

● main.c

   1: #include "UserDef.h"
   2:  
   3: int main()
   4: {
   5:     int iRow;
   6:     int iCol;
   7:  
   8:     system("cls");
   9:     PrintRect(10, 10, 20, 10);
  10:     PutChar(15, 15, 'A');
  11:     getch();
  12:     system("cls");
  13:     
  14:     return 0;
  15: }



● UserDef.c

   1: #include "UserDef.h"
   2:  
   3: /*********************************************************************
   4:     기  능: 화면에 한 문자를 출력하는 함수
   5:     설  명: RAM -> VideoRAM 전달 되는 영역에 문자를 출력.
   6:     인  자:    1. ucX축 시작좌표
   7:             2. ucY축 시작좌표
   8:             3. 출력될 문자
   9: *********************************************************************/
  10: void PutChar(unsigned char ucX, unsigned char ucY, unsigned char ucData)
  11: {
  12:     char far *location;
  13:     char attr = 7;
  14:     
  15:     location = (char far *)0xb8000000 + ucY * 160 + ucX * 2;
  16:     *location++ = ucData;
  17:     *location = attr;
  18:  
  19:     return ;
  20: }
  21:  
  22: /*********************************************************************
  23:     기  능: 화면에 사각형박스를 그리는 함수
  24:     설  명: PutChar()를 사용.
  25:     인  자:    1. X축 시작좌표
  26:             2. Y축 시작좌표
  27:             3. 박스의 폭
  28:             4. 박스의 높이
  29: *********************************************************************/
  30: void PrintRect(unsigned char ucX, unsigned char ucY, 
  31:                 unsigned char width, unsigned char height) 
  32: {
  33:     unsigned char ucRow = ucY;
  34:     unsigned char ucCol = ucX;
  35:     
  36:     // 상단
  37:     PutChar(ucCol, ucRow, PEN_LT);
  38:     for(++ucCol ; ucCol < ucX + width - 1 ; ++ucCol)
  39:     {
  40:         PutChar(ucCol, ucRow, PEN_GARO);
  41:     }
  42:     // 우측
  43:     PutChar(ucCol, ucRow, PEN_RT);
  44:     for(++ucRow ; ucRow < ucY + height - 1 ; ++ucRow)
  45:     {
  46:         PutChar(ucCol, ucRow, PEN_SERO);
  47:     }
  48:     
  49:     // 하단
  50:     PutChar(ucCol, ucRow, PEN_RB);
  51:     for(--ucCol ; ucCol > ucX ; --ucCol)
  52:     {
  53:         PutChar(ucCol, ucRow, PEN_GARO);
  54:     }
  55:  
  56:     // 좌측
  57:     PutChar(ucCol, ucRow, PEN_LB);
  58:     for(--ucRow ; ucRow > ucY ; --ucRow)
  59:     {
  60:         PutChar(ucCol, ucRow, PEN_SERO);
  61:     }
  62:  
  63:     return ;
  64: }



● 실행결과

image
 

사각형박스 안에는 ‘A’가 살고 있다.

 

4일차…PrintRect( )의 구현


2011년 10월 14일...PrintRect( )의 구현
                       사실 이전에 PrintRect( )를 구현하기 위해 많은 삽질을 하였음. 좌표계산미스에..
                       조건문을 잘 못하여 열린 도형이 만들어지던가 등등..

● main.c

   1: #include "UserDef.h"
   2:  
   3: int main()
   4: {
   5:     int iRow;
   6:     int iCol;
   7:  
   8:     system("cls");
   9:     PrintRect(0, 0, 80, 25);
  10:     PrintRect(10, 10, 60, 5);
  11:     
  12:     getch();
  13:     system("cls");
  14:     
  15:     return 0;
  16: }



● UserDef.c은 3일차와 같음. (이 날 뭐한거냐 ㅋㅋ)

image

아마 이 날은 PrintRect( )에 최대값을 넣어 창을 벗어나는지 테스트해본것 같다.
우왕 4일 동안 이것밖에 못 하다니...

 

5일차…PrintRect( )의 구현



2011년 10월 31일…이 날은 좀 많이 했다.

● main.c

   1: // 원라인 에디터 프로젝트
   2: #include "UserDef.h"
   3:  
   4: int main()
   5: {
   6:     int iRow;
   7:     int iCol;
   8:  
   9:     // 1단계...텍스트 에디터 창 만들기 
  10:     system("cls");
  11:     PrintRect(0, 7, 80, 12);        // 최외곽 사각형
  12:     PrintRect(0, 7, 80, 3);            // 상단 메뉴
  13:     PrintRect(1, 10, 78, 5);        // 에디트박스 외
  14:     PrintRect(2, 11, 76, 3);        // 에디트박스 내
  15:     PrintRect(1, 15, 78, 3);        // 하단 메뉴
  16:     PutChar(0, 9, PEN_GL);
  17:     PutChar(79, 9, PEN_GR);
  18:     
  19:     PutString(5, 8, "New      Load      Save      Save as      Exit");
  20:     PutString(9, 16, "F10 - Menu         Alt + x - Exit         F1 - Help");
  21:     
  22:     // 2단계...메뉴 만들기
  23:     
  24:     
  25:     getch();
  26:     system("cls");
  27:     
  28:     return 0;
  29: }


● UserDef.c

   1: #include "UserDef.h"
   2:  
   3: /*********************************************************************
   4:     기  능: 화면에 한 문자를 출력하는 함수
   5:     설  명: RAM -> VideoRAM 전달 되는 영역에 문자를 출력.
   6:     인  자:    1. ucX축 시작좌표
   7:             2. ucY축 시작좌표
   8:             3. 출력될 문자
   9: *********************************************************************/
  10: void PutChar(unsigned char ucX, unsigned char ucY, unsigned char ucData)
  11: {
  12:     char far *location;
  13:     char attr = 7;
  14:     
  15:     location = (char far *)0xb8000000 + ucY * 160 + ucX * 2;
  16:     *location++ = ucData;
  17:     *location = attr;
  18:  
  19:     return ;
  20: }
  21:  
  22: /*********************************************************************
  23:     기  능: 화면에 문자열을 출력하는 함수
  24:     설  명: RAM -> VideoRAM 전달 되는 영역에 문자열을 출력.
  25:     인  자:    1. ucX축 시작좌표
  26:             2. ucY축 시작좌표
  27:             3. 출력될 문자열
  28: *********************************************************************/
  29: void PutString(unsigned char ucX, unsigned char ucY, void *vpStr)
  30: {
  31:     while('\0' != *((unsigned char *)vpStr))
  32:     {
  33:         PutChar(ucX, ucY, *((unsigned char *)vpStr));
  34:         ++ucX;
  35:         ((unsigned char *)vpStr)++;
  36:     }
  37:     
  38:     return ;
  39: }
  40:  
  41: /*********************************************************************
  42:     기  능: 화면에 사각형박스를 그리는 함수
  43:     설  명: PutChar()를 사용.
  44:     인  자:    1. X축 시작좌표
  45:             2. Y축 시작좌표
  46:             3. 박스의 폭
  47:             4. 박스의 높이
  48: *********************************************************************/
  49: void PrintRect(unsigned char ucX, unsigned char ucY, 
  50:                 unsigned char width, unsigned char height) 
  51: {
  52:     unsigned char ucRow = ucY;
  53:     unsigned char ucCol = ucX;
  54:     
  55:     // 상단
  56:     PutChar(ucCol, ucRow, PEN_LT);
  57:     for(++ucCol ; ucCol < ucX + width - 1 ; ++ucCol)
  58:     {
  59:         PutChar(ucCol, ucRow, PEN_GARO);
  60:     }
  61:     // 우측
  62:     PutChar(ucCol, ucRow, PEN_RT);
  63:     for(++ucRow ; ucRow < ucY + height - 1 ; ++ucRow)
  64:     {
  65:         PutChar(ucCol, ucRow, PEN_SERO);
  66:     }
  67:     
  68:     // 하단
  69:     PutChar(ucCol, ucRow, PEN_RB);
  70:     for(--ucCol ; ucCol > ucX ; --ucCol)
  71:     {
  72:         PutChar(ucCol, ucRow, PEN_GARO);
  73:     }
  74:  
  75:     // 좌측
  76:     PutChar(ucCol, ucRow, PEN_LB);
  77:     for(--ucRow ; ucRow > ucY ; --ucRow)
  78:     {
  79:         PutChar(ucCol, ucRow, PEN_SERO);
  80:     }
  81:  
  82:     return ;
  83: }


● 실행결과

image






★ 추가 ㅠㅠ

   1: #ifndef    __USERDEF_H__
   2: #define    __USERDEF_H__
   3:  
   4: #define    PEN_SERO    179        // ─
   5: #define    PEN_GARO    196        // │
   6: #define    PEN_LT        218        // ┌
   7: #define    PEN_RT        191        // ┐
   8: #define    PEN_LB        192        // └
   9: #define    PEN_RB        217        // ┘
  10: #define    PEN_GL        195        // ├
  11: #define    PEN_GR        180        // ┤
  12:  
  13: #define    NULL    ((void *)0)    
  14:  
  15:  
  16: void PutChar(unsigned char x, unsigned char y, unsigned char ucData);
  17: void PrintRect(unsigned char x, unsigned char y, 
  18:                 unsigned char width, unsigned char height);
  19:  
  20: #endif    //__USERDEF_H__

UserDef.h를 미기재하여 올림.
이 파일은 UserDef.c에 정의된 함수의 원형(prototype)과 ASCII에 대응하는 테두리를 정의하였음.