pdcurses 를 컴파일하여 Visual C++ 용 라이브러리 만들기

프롬프트> nmake -f vcwin32.mak

 

* 테스트용 소스 파일:  helloworld.c (http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/helloworld.html 에 있는 ncurses 용 소스에서 인클루드 문의 ncurses.h 를 curses.h 로 변경한 것 뿐임)

/*
 * Filename: helloworld.c
 *
 * Compile: cl /c helloworld.c /I .
 *       Link: link -nologo helloworld.obj pdcurses.lib user32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib
*   Or
 * Compile & Link: cl helloworld.c -I . pdcurses.lib user32.lib gdi32.lib shell32.lib comdlg32.lib
 *
 * Execute: helloworld
 *
 * Date: 2014. 1. 15.
 */

#include <curses.h>           /* changed from <ncurses.h> */

int main()

    initscr();                          /* Start curses mode     */


    printw("Hello World !!!");    /* Print Hello World    */
    refresh();                         /* Print it on to the real screen */
    getch();                          /* Wait for user input */

    endwin();                        /* End curses mode    */

    return 0;
}

 

* 실행 결과:

 

 

 

Posted by Scripter
,

ncurses(또는 curses) 는 Linux/Unix 계열의 환경에서 VT100 등의 터미널과 호환되는 윈도우형 입출력 라이브러이다. 이를 이용하면 윈도우의 임의의 위치에 출력도 하고, 임의의 위치에서 입력을 받을 수도 있다.

* 카라슈바 곱셈 참조

다음은 Linux 나 Cygwin 환경에서 파이썬 2.7.x 로 실행되도록 작성된 소스이다.

 

# Filename: ezMult_003.py
#
#  Execute: python ezMult_003.py
#
#     Date: 2014. 1. 10.

import curses
import curses.textpad
import random


stdscr = curses.initscr()
curses.start_color()   #
curses.nonl()
curses.noecho()
curses.cbreak()
stdscr.keypad(1)

# Initialize few color pairs
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_GREEN)
curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_GREEN)
curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_GREEN)
curses.init_pair(4, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
curses.init_pair(5, curses.COLOR_CYAN, curses.COLOR_BLACK)
curses.init_pair(6, curses.COLOR_WHITE, curses.COLOR_BLACK)
curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_WHITE)

x0 = int(random.random()*90) + 10
y0 = int(random.random()*90) + 10
z0 = x0*y0
s01 = int(x0/10)*int(y0/10)
s02 = (x0%10)*(y0%10)
t0 = int(x0/10)*(y0%10) + (x0%10)*int(y0/10)

stdscr.addstr(3, 4, "%4d" % x0)
stdscr.addstr(4, 3, "x%4d" % y0)
stdscr.addstr(5, 3, "-----")
stdscr.addstr(6, 4, "%2d%02d" % (s01, s02))
stdscr.addstr(7, 4, "%3d" % t0)
stdscr.addstr(8, 3, "-----")
stdscr.addstr(9, 4, "%4d" % z0)

x = int(random.random()*90) + 10
y = int(random.random()*90) + 10
z = x*y
s1 = int(x/10)*int(y/10)
s2 = (x%10)*(y%10)
t = int(x/10)*(y%10) + (x%10)*int(y/10)

o1 = 0
o2 = 0
o3 = 0
if s1 < 10:
    o1 = 1
if t < 100:
    o2 = 1
if z < 1000:
    o3 = 1

stdscr.addstr(3, 14, "%4d" % x)
stdscr.addstr(4, 13, "x%4d" % y)
stdscr.addstr(5, 13, "-----")
stdscr.addstr(8, 13, "-----")
stdscr.move(6, 14)
stdscr.refresh()

curses.nl()
curses.noecho()

win4 = curses.newwin(14, 48, 3, 28)
win5 = curses.newwin(2, 78, 21, 0)
   
win4.addstr(0, 0, "Ctrl-A Go to left edge of edit box.")
win4.addstr(1, 0, "Ctrl-B Cursor left.")
win4.addstr(2, 0, "Ctrl-D Delete character under cursor.")
win4.addstr(3, 0, "Ctrl-E Go to right edge of edit box.")
win4.addstr(4, 0, "Ctrl-F Cursor right.")
win4.addstr(5, 0, "Ctrl-G Terminate, returning the box's contents.")
win4.addstr(6, 0, "Ctrl-H Delete character backward.")
win4.addstr(7, 0, "Ctrl-J Terminate if the edit box is 1 line.")
win4.addstr(8, 0, "Ctrl-K Clear to end of line.")
win4.addstr(9, 0, "Ctrl-L Refresh screen.")

win4.refresh()
# win4.getch()

win1 = curses.newwin(1, 5, 6, 14)   # (h,w,y,x)
win2 = curses.newwin(1, 4, 7, 14)   # (h,w,y,x)
win3 = curses.newwin(1, 5, 9, 14)   # (h,w,y,x)
win1.bkgd(curses.color_pair(1))
win2.bkgd(curses.color_pair(1))
win3.bkgd(curses.color_pair(1))
win1.refresh()
win2.refresh()
win3.refresh()
win1.move(0,0)

box1 = curses.textpad.Textbox(win1, insert_mode=True)
box2 = curses.textpad.Textbox(win2, insert_mode=True)
box3 = curses.textpad.Textbox(win3, insert_mode=True)
a1 = box1.edit()
win2.move(0,0)
a2 = box2.edit()
win3.move(0,0)
a3 = box3.edit()

stdscr.move(15, 0)
stdscr.attron(curses.color_pair(6))

try:
    tmp1 = int(a1)
    tmp2 = int(a2)
    tmp3 = int(a3)
    stdscr.addstr(15, 0, "Your answers are")
    stdscr.addstr(16, 0, "            %4d"% int(a1))
    stdscr.addstr(17, 0, "            %3d"% int(a2))
    stdscr.addstr(18, 0, "            %4d"% int(a3))

    stdscr.addstr(15, 20, "Right answers are")
    stdscr.addstr(16, 20, "             %2d%02d"% (s1, s2))
    stdscr.addstr(17, 20, "             %3d"% t)
    stdscr.addstr(18, 20, "             %4d"% z)

    if int(a1) == s1*100 + s2 and int(a2) == t and int(a3) == z:
     stdscr.addstr(20, 0, "Yours are right... ")
    else:
     stdscr.addstr(20, 0, "Yours are wrong... ")

    stdscr.getch()
except:
    stdscr.addstr(15, 0, "Some invalid charactres are found... ")
    stdscr.refresh()
    stdscr.getch()
finally:
    curses.nl()
    curses.nocbreak(); stdscr.keypad(0); curses.echo()
    curses.endwin()

 

Textbox 에서 입력 받을 스트링의 길이가 4인 경우 너비를 4+1 로 잡아야 하므로 배경색(녹색0의 너비가 4+1 로 나오는 것은 어쩔 수 없다. 한 Textbox 에서 입력을 마친 후 다음 Textbox 로 가려면 Enter Ctrl+G, Ctrl+J 키중 하나를 누르면 된다. Ctrl+D 는 커서가 놓인 곳의 글자를 지우는 키이고, Ctrl+H 는 커서 좌측의 글자를 지우면서 좌특으로 커서를 이동하는 키 (즉, Bacpspace 아 같은 역하를 하는 키이다.) Backspace 키는 Textbox 에서 동작하지 않는다. Ctrl+B 또는 키패드의 좌즉 화살표 키는 Textbox 안에서 좌측으로 한 칸씩 이동하는 키이고, Ctrl+F 또는 키패드의 우측 화살표 키는 Textbox 안에서 우측으로 한 칸씩 이동하는 키이다. 커서가 어느 Textbox 를 벗어나면 그 textbox 로는 다시 돌아갈 수 없다. 또 한 Textbox 의 우측 끝에 커서가 위치하면 글자 입력이 되지 않는다.

 

* 실행 결과:

 

 

 

Posted by Scripter
,

ncurses(또는 curses) 는 Linux/Unix 계열의 환경에서 VT100 등의 터미널과 호환되는 윈도우형 입출력 라이브러이다. 이를 이용하면 윈도우의 임의의 위치에 출력도 하고, 임의의 위치에서 입력을 받을 수도 있다.

* 카라슈바 곱셈 참조

다음은 Linux 나 Cygwin 환경이면 gcc 로 컴파일하여 실행되는 C 소스이다.

 

/*
 * Filename: ezmult_003.c
 *
 * Compile: gcc -o ezmult_003 ezmult_003.c -lform -lncurses
 *
 * Execute: ./ezmult_003
 *
 *    Date: 2014. 1. 6. (Mon)  v0.002
 *    Date: 2014. 1. 8. (Wed)  v0.003
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <form.h>
#include <ncurses.h>

int main()
{
    int x0, y0, z0;
    int s01, s02, t0;
    int x, y, z;
    int s1, s2, t;
    int i, j;
    int flag_insert_mode = 1;
    int o1 = 0;
    int o2 = 0;
    int o3 = 0;

    FIELD *field[4];
    FORM  *my_form;
    int ch;
 
    /* curses 초기화하기 */
    initscr();
    start_color();    // 색상을 사용하려면 initscr() 호출 후 즉시 이를 호출해야 함
    nonl();            // 필드에서 엔터 키가 작용되게 하기 위함
    cbreak();
    noecho();
    keypad(stdscr, TRUE);


    srand(time(NULL));
    x = rand()/(RAND_MAX + 1.0)*90 + 10;
    y = rand()/(RAND_MAX + 1.0)*90 + 10;
    z = x*y;
    s1 = (x/10)*(y/10);
    s2 = (x%10)*(y%10);
    t = (x/10)*(y%10) + (x%10)*(y/10);
   
    if (s1 < 10)
    {
         o1 = 1;
    }
    if (t < 100)
    {
         o2 = 1;
    }
    if (z < 1000)
    {
         o3 = 1;
    }
    refresh();
    

    /* 필드 초기화 */
    field[0] = new_field(1, 4-o1,  6, 14+o1, 0, 0);
    field[1] = new_field(1, 3-o2,  7, 14+o2, 0, 0);
    field[2] = new_field(1, 4-o3,  9, 14+o3, 0, 0);
    field[3] = NULL;


    /* 폼 생성하여 붙여 넣기 */
    my_form = new_form(field);
    post_form(my_form);
    refresh();


     /* 색상 초기화 */
    init_pair(1, COLOR_WHITE, COLOR_GREEN);
    init_pair(2, COLOR_WHITE, COLOR_GREEN);
    init_pair(3, COLOR_WHITE, COLOR_GREEN);
    init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
    init_pair(5, COLOR_CYAN, COLOR_BLACK); 
    init_pair(6, COLOR_WHITE, COLOR_BLACK);
    init_pair(7, COLOR_BLACK, COLOR_WHITE);


    x0 = rand()/(RAND_MAX + 1.0)*90 + 10;
    y0 = rand()/(RAND_MAX + 1.0)*90 + 10;
    z0 = x0*y0;
    s01 = (x0/10)*(y0/10);
    s02 = (x0%10)*(y0%10);
    t0 = (x0/10)*(y0%10) + (x0%10)*(y0/10);


    mvprintw(3, 4, "%4d", x0);
    mvprintw(4, 3, "x%4d", y0);
    mvprintw(5, 3, "-----");
    mvprintw(6, 4, "%2d%02d", s01, s02);
    mvprintw(7, 4, "%3d", t0);
    mvprintw(8, 3, "-----");
    mvprintw(9, 4, "%4d", z0);
    refresh();


    mvprintw(3, 14, "%4d", x);
    mvprintw(4, 13, "x%4d", y);
    mvprintw(5, 13, "-----");
    mvprintw(8, 13, "-----");
    attron(COLOR_PAIR(7));
    mvprintw(0, 0, "Ins");
    attron(COLOR_PAIR(6));
    move(6, 14);
    refresh();


    set_field_type(field[0], TYPE_INTEGER, 0, 0, 9999);
    set_field_type(field[1], TYPE_INTEGER, 0, 0, 999);
    set_field_type(field[2], TYPE_INTEGER, 0, 0, 9999);
    field_opts_on(field[0], O_EDIT);
    field_opts_on(field[1], O_EDIT);
    field_opts_on(field[2], O_EDIT);
    field_opts_on(field[0], O_ACTIVE);
    field_opts_on(field[1], O_ACTIVE);
    field_opts_on(field[2], O_ACTIVE);

 
    /* 필드 옵션 설정 */
    set_field_back(field[0], A_UNDERLINE); 
    set_field_back(field[1], A_UNDERLINE); 

    set_field_back(field[2], A_UNDERLINE); 


    /* 필드 옵션 설정 */
    set_field_fore(field[0], COLOR_PAIR(1));
    set_field_back(field[0], COLOR_PAIR(2));
    set_field_fore(field[1], COLOR_PAIR(1));

    set_field_back(field[1], COLOR_PAIR(2));
    set_field_fore(field[2], COLOR_PAIR(1));
    set_field_back(field[2], COLOR_PAIR(2));


    if (s1 >= 10)
        move(6, 14);
    else
        move(6, 15);
    refresh();


    /* 사용자 요구에 따라 번복 여부 결정 */
    while((ch = getch()) != KEY_F(1) && ch != 0x1B && ch != 0x0D)   
        switch(ch)
      {

           case KEY_DOWN:
           case KEY_ENTER:
               /* 다음 필드로 가기 */
               form_driver(my_form, REQ_NEXT_FIELD);
               break;
          case KEY_UP:
              /* 이전 필드로 가기 */
              form_driver(my_form, REQ_PREV_FIELD);
              break;
         case KEY_BACKSPACE:
         case 0x7F:
              form_driver(my_form, REQ_DEL_PREV);
              break;
         case KEY_IC:
              if (flag_insert_mode != 0)
             {
                 form_driver(my_form, REQ_OVL_MODE);
                 getyx(stdscr, j, i);
                 mvprintw(0, 0, "   ");
                 move(j, i);
                 flag_insert_mode = 0;
             }
             else
            {
                 form_driver(my_form, REQ_INS_MODE);
                 getyx(stdscr, j, i);
                attron(COLOR_PAIR(7));
                mvprintw(0, 0, "Ins");
                attron(COLOR_PAIR(6));
                move(j, i);
                flag_insert_mode = 1;
            }
            break;
        case KEY_DC:
            form_driver(my_form, REQ_DEL_CHAR);
            break;
        case KEY_LEFT:
            form_driver(my_form, REQ_LEFT_CHAR);
            break;
        case KEY_RIGHT:
            form_driver(my_form, REQ_RIGHT_CHAR);
            break;
        default:
            form_driver(my_form, ch);
            break;
       }
    }
 
    form_driver(my_form, REQ_NEXT_FIELD);
 
    attron(COLOR_PAIR(6));
    mvprintw(13, 0, "You have answered");
    if (atoi(field_buffer(field[0], 0)) == s1*100 + s2)
         attron(COLOR_PAIR(5));
    else
         attron(COLOR_PAIR(4));
    mvprintw(14, 8, "%4d", atoi(field_buffer(field[0], 0)));
    if (atoi(field_buffer(field[1], 0)) == t)
         attron(COLOR_PAIR(5));
    else
         attron(COLOR_PAIR(4));
    mvprintw(15, 8, "%3d", atoi(field_buffer(field[1], 0)));
    if (atoi(field_buffer(field[2], 0)) == z)
         attron(COLOR_PAIR(5));
    else
         attron(COLOR_PAIR(4));
    mvprintw(16, 8, "%4d", atoi(field_buffer(field[2], 0)));

    attron(COLOR_PAIR(6));
    mvprintw(13, 20, "Right answer is");
    mvprintw(14, 28, "%2d%02d", s1, s2);
    mvprintw(15, 28, "%3d", t);
    mvprintw(16, 28, "%4d", z);
    if (atoi(field_buffer(field[0], 0)) == s1*100 + s2
         && atoi(field_buffer(field[1], 0)) == t
         && atoi(field_buffer(field[2], 0)) == z)
        mvprintw(18, 0, "    Your answer is right.");
    else
        mvprintw(18, 0, "    Your answer is wrong.");
    mvprintw(21, 0, "Press any key to quit...");
    getch();
   
    /* 폼을 떼어내고 메모리를 해제한다. */
    unpost_form(my_form);
    free_form(my_form);
    free_field(field[0]);
    free_field(field[1]);
    free_field(field[2]);

    endwin();

    return 0;
}
 

 

* 실행 결과:

 


 

Posted by Scripter
,

32bit OS 에서는 int 타입과 long 타입이 다 같이 4바이트의 크기를 갖지만.

64bit OS 에서는 int 타입이 4바이트, long 타입이 8바이트의 크기를 갖는다.

그렇다면 64비트 리눅스 환경에서 32비트 용으로 작성된 C 소스를 gcc 로 컴파일하려면 어떻게 해야 할까? 

 

// Filename: testIntSize.c

int main()
{
#include <stdio.h>

int main()
{
    printf("sizeof(int) = %d\n", sizeof(int));
    printf("sizeof(long) = %d\n", sizeof(long));

    return 0;
}

 

# 64비트 용으로 컴파일하고 실행하기

$ gcc -o testIntSize testIntSize.c

$ ./testIntSize

sizeof(int) = 4
sizeof(long) = 8

 

# 32비트 용으로 컴파일하고 실행하기 (옵션 -m32 추가)

$ gcc -m32 -o testIntSize testIntSize.c

$ ./testIntSize

sizeof(int) = 4
sizeof(long) = 4

 

 

Posted by Scripter
,