下面將全屏編輯器修改一下,通過panel的支持,讓它能同時打開3個窗口編輯不同的內容,同時對3個窗口的內容進行保存。
效果如下:
#include <locale.h>
#include <stdio.h>
#include <panel.h>
#include <ncurses.h>
//code by [email protected]
//date:2014/1/17
int isExist(char *filename)
{
return (access(filename, 0) == 0);
}
int main(int argc, char *argv[])
{
MEVENT event;
setlocale(LC_ALL,"");
initscr();
clear();
noecho();
cbreak();
if(has_colors() == FALSE)
{
endwin();
printf("你的終端不支持色彩!\n");
return (1);
}
start_color(); /啓動color 機制/
mvprintw(3,COLS/2-10,"簡單編輯器-僅限於單個屏幕的編輯");
mvprintw(4,COLS/2-20,"【F9讀保存內容,F10存盤,F11退出,F12刪除整行,TAB換窗口】");
refresh();
init_pair(1, COLOR_GREEN, COLOR_BLACK);
init_pair(2, COLOR_BLUE, COLOR_BLACK);
init_pair(3, COLOR_RED,COLOR_BLACK);
WINDOW *mywins[3];
PANEL *top;
PANEL *mypanels[3];
char filename[10];
int width=COLS-18;
int height=LINES-18;
int x,y;
int begin_y=5;int begin_x=5;
int i;
for(i = 0; i < 3; +++i)
{
mywins[i]=newwin(height,width,begin_y,begin_x);//新窗口(行,列,begin_y,begin_x)
keypad(mywins[i],TRUE);
wattron(mywins[i],COLOR_PAIR(i+1));
mypanels[i] = new_panel(mywins[i]);
box(mywins[i],ACS_VLINE,ACS_HLINE);
wattroff(mywins[i],COLOR_PAIR(i+1));
begin_y+=4;begin_x+=4;
}
set_panel_userptr(mypanels[0],mypanels[1]);
set_panel_userptr(mypanels[1],mypanels[2]);
set_panel_userptr(mypanels[2],mypanels[0]);
top = mypanels[2];
update_panels();
doupdate();
int nowwinid=2;
sprintf(filename,"myed%d.dat",nowwinid);
getyx(mywins[nowwinid],y,x);
++y;++x;
mmask_t oldmousemask;
int ans=0;
FILE *fp2=NULL;
FILE *fp1=NULL;
mousemask(ALL_MOUSE_EVENTS, &oldmousemask);
while(1){
int c=mvwgetch(mywins[nowwinid],y,x);
switch(c)
{ case KEY_MOUSE:
if(getmouse(&event) == OK)
{ / When the user clicks left mouse button /
if(event.bstate & BUTTON1_PRESSED)
{
y=event.y-7;x=event.x-7;
wmove(mywins[nowwinid],y,x);
}
}
break;
case KEY_BACKSPACE:
--x;
if (x<1){
--y;x=width-2;
}
if (y<1){
y=height-2;
}
mvwprintw(mywins[nowwinid],y,x," ");
break;
case KEY_RIGHT:
++x;
if (x>=width-1) {
++y;
x=1;
}
break;
case KEY_LEFT: --x;
if (x<1){
--y;
x=width-2;
}
break;
case KEY_UP:
--y;
if (y<1){
y=height-2;
}
break;
case KEY_DOWN:
++y;
if (y>=height-1){
y=1;
}
break;
case 10:
++y;
if (y>=height-1){
y=1;
}
break;
case KEY_F(11):
//退出
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"退出編輯器嗎? ");
mvprintw(LINES-2,2," ");
mvprintw(LINES-1,2," \n");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
mvprintw(LINES-2,2,"是\n");
refresh();
wattroff(mywins[nowwinid],COLOR_PAIR(1));
mousemask(oldmousemask,NULL);
endwin();
return 0;
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case 9:
top = (PANEL *)panel_userptr(top);
top_panel(top);
update_panels();
doupdate();
nowwinid=(++nowwinid)%3;
sprintf(filename,"myed%d.dat",nowwinid);
break;
case KEY_F(10):
//存盤
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"保存當前內容嗎? ");
mvprintw(LINES-2,2," ");
mvprintw(LINES-1,2," \n");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
mvprintw(LINES-3,2," ");
fp1 = fopen(filename,"wb");
if (fp1!=NULL){
int jg= putwin(mywins[nowwinid],fp1);
fclose(fp1);
if (jg==OK) mvprintw(LINES-1,2,"保存成功!\n");
}
mvprintw(LINES-3,2,"保存當前內容嗎? ");
mvprintw(LINES-2,2,"是\n");
refresh();
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(9):
//讀取存盤
mvprintw(LINES-3,2," ");
mvprintw(LINES-3,2,"讀取保存內容嗎? ");
mvprintw(LINES-2,2," ");
mvprintw(LINES-1,2," \n");
refresh();
ans=getch();
if (ans=='Y' ||ans=='y')
{
if (isExist(filename)) {
fp2 = fopen(filename,"rb");
if (fp2!=NULL){
WINDOW *newwin=getwin(fp2);
if (newwin!=NULL) {
WINDOW *temp=mywins[nowwinid];
mywins[nowwinid]=newwin;
delwin(temp);
PANEL *temppan=mypanels[nowwinid];
mypanels[nowwinid] = new_panel(mywins[nowwinid]);
del_panel(temppan);
set_panel_userptr(mypanels[0],mypanels[1]);
set_panel_userptr(mypanels[1],mypanels[2]);
set_panel_userptr(mypanels[2],mypanels[0]);
top = mypanels[nowwinid];
top_panel(top);
update_panels();
doupdate();
mvprintw(LINES-1,2,"讀取成功!\n");
}
fclose(fp2);
}
}
mvprintw(LINES-3,2,"讀取保存內容嗎? ");
mvprintw(LINES-2,2,"是\n");
refresh();
}else
mvprintw(LINES-2,2,"否\n");
refresh();
break;
case KEY_F(12):
//刪除某行
wdeleteln(mywins[nowwinid]);
winsertln(mywins[nowwinid]);
box(mywins[nowwinid],ACS_VLINE,ACS_HLINE);
break;
case KEY_DC:
//刪除某字符
mvwprintw(mywins[nowwinid],y,x," ");
break;
default:
mvwprintw(mywins[nowwinid],y,x,"%c",c);
++x;
if (x>=width-1){
++y;
x=1;
}
if (y>=height-1){
y=1;
}
doupdate();
}
}
return 0;
}
dp@dp:~/cursestest % gcc -lncursesw -lpanel a.c -o mytest
dp@dp:~/cursestest % ./mytest
編寫含有表單的程序,一般步驟如下:
1. 初始化並進入curses
2. 用new_field()函數創建表單域。你可以指定域的高度,寬度以及它在表單中的位
置。
3. 指定已創建的表單域所作用的表單,並用new_form()函數創建表單。
4. 用post_form()函數來遞送表單,並刷新屏幕。
5. 用一個循環來處理用戶請求,通過form_driver()函數對錶單做相應的更新。
6. 用unpost_form()函數取消表單的遞送。
7. 用free_form()函數釋放已分配給表單的內存。
8. 用free_field()函數釋放已分配給菜單項的內存。
9. 退出curses 模式
下面演示了表單的操作基礎
#include <form.h>
int main()
{
FIELD *field[3];
FORM *my_form;
int ch;
/* 初始化curses */
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
/* 初始化表單域*/
field[0] = new_field(1, 10, 4, 18, 0, 0);
field[1] = new_field(1, 10, 6, 18, 0, 0);
field[2] = NULL;
/* 設置表單域*/
set_field_back(field[0],A_UNDERLINE); /* 爲選項打印一條下滑線*/
field_opts_off(field[0],O_AUTOSKIP);
/* 在域(輸入框)填滿後光標不會自動跳到下一個表單域*/
set_field_back(field[1],A_UNDERLINE);
field_opts_off(field[1],O_AUTOSKIP);
/* 創建並遞送表單*/
my_form = new_form(field);
post_form(my_form);
refresh();
mvprintw(4, 10, "name:");
mvprintw(6, 10, "age:");
refresh();
move(4,15);
/* 用循環獲取用戶請求,F12退出*/
while((ch = getch()) != KEY_F(12))
{
switch(ch)
{
case KEY_DOWN:
/* 跳至下一個表單域*/
form_driver(my_form,REQ_NEXT_FIELD);
/* 跳到當前緩衝的末尾*/
/* 精確地在輸入最後一個後字符跳出這個表單域*/
form_driver(my_form,REQ_END_LINE);
break;
case KEY_UP:
/* 移動到前一個表單域*/
form_driver(my_form,REQ_PREV_FIELD);
form_driver(my_form,REQ_END_LINE);
break;
default:
/* 如果輸入的是普通字符, 就把它打印出來*/
form_driver(my_form,ch);
break;
}
}
/* 取消表單並釋放內存*/
unpost_form(my_form);
free_form(my_form);
free_field(field[0]);
free_field(field[1]);
endwin();
return 0;
}
dp@dp:~/cursestest % gcc -lncursesw -lform b.c -o mytest
dp@dp:~/cursestest % ./mytest