EGL--标准基础类实现文件 STDEG.INC

/*
  STDEG.INC
*/

BOOL CheckChineseOs(void)
{
  outportb(0x03ce,0x06);
  return( (peekb(0x0040,0x0049)==3 && inportb(0x03cf)&0x0F!=0x0e)?1:0 );
}

void InitGr(void)
{
   int gd=VGA,gm=VGAHI;
   static UINT hadinit=0;
   if( hadinit>0 ) return; /* 防止重复调用初始化函数 */
   hadinit++;
   if( CheckChineseOs() ){
     printf("/
     /n注意:/
     /nE.G.被设计成在英文DOS方式下运行/
     /n如果被运行在中文DOS下,可能出现一些与原设计相悖的情况./
     /n/n按ESC键退出 E.G. 环境,其它键强制运行/
     /n");
     if( GetKey()==ESC ) exit(0);
     }
   initgraph(&gd,&gm,"");
   if( graphresult()!=grOk ){
     printf("/nE.G. can not initializes graphics.");
     exit(1);
     }
   printf("Check HIMEM.SYS . . .");
   if( !xms_init() ){
     closegraph();
     printf("/nXMS device not installed or not enough memory.");
     exit(1);
     }
   printf("done");
   printf("/nLoad HZK16 & ASC16 to XMS . . .");
   if( (xms_hzk16=xms_malloc(270))==ERROR ){
     end_xms();
     closegraph();
     printf("/nError alloc XMS memory to load HZK16.");
     exit(1);
     }
   if( (xms_asc16=xms_malloc(5))==ERROR ){
     xms_free(xms_hzk16);
     end_xms();
     closegraph();
     printf("/nError alloc XMS memory to load ASC16.");
     exit(1);
     }
   if( load_hzk16_2_xms()==ERROR ){
   /* 不可以在此释放分配给字库和ASCII码的XMS内存,因它们已在装载函数内释放 */
     end_xms();
     closegraph();
     printf("/nError load HZK16 or ASC16 to XMS.");
     exit(1);
     }
   printf("done");
   printf("/nCheck MOUSE . . .");
   reset_mouse();
   if( !MOUSE_THERE ){
     xms_free(xms_hzk16);
     xms_free(xms_asc16);
     end_xms();
     closegraph();
     printf("/nMOUSE not installed.");
     exit(1);
     }
   mouse_off();
   printf("done");
   printf("/nEasy Graphics initializes OK!");
   mouse_on();
   InstallEvent();
   InitTimer();
   atexit( CloseGr ); /* 注册退出函数,当中途意外调用exit时,保证系统不崩溃 */
}

void CloseGr(void)
{
   static UINT hadclose=0;
   if( hadclose>0 ) return; /* 防止重复调用退出函数 */
   hadclose++;
   EndTimer();
   set_event_handler(0,0);
   xms_free( xms_hzk16 );
   xms_free( xms_asc16 );
   end_xms();
   closegraph();
}

BOOL InBar(int x,int y,int l,int t,int r,int b)
{
  return( (x>=l && x<=r && y>=t && y<=b)?1:0 );
}

int Max(int a,int b)
{
  return( a>=b?a:b );
}

void FillBar(int l,int t,int r,int b,int style,int bkground)
{
  struct fillsettingstype f;
  getfillsettings(&f);
  setfillstyle(style,bkground);
  mouse_off();
  bar(l,t,r,b);
  mouse_on();
  setfillstyle(f.pattern,f.color);
}

BOOL WinMake(int l,int t,int r,int b,int bc,int frame,int status)
{
   int i,frame_thick,color1,color2;
   if( frame==NULL_FRAME ) return(OK);
   switch(frame){
     case STD_FRAME:  /* 类似win95中菜单的边框 */
   frame_thick=2; break;
     case BUTTON_FRAME:  /* 边框宽度只有1个 */
   frame_thick=1; break;
     case SHADOWLINE_FRAME: /* 带有阴阳线的边框 */
          FillBar(l,t,r,b,SOLID_FILL,bc);
   mouse_off();
   setcolor(15);    line(l,t,r,t);       line(l,t,l,b);
          setcolor(8);  line(r,t,r,b);  line(l,b,r,b);
   setcolor(8);
   for(i=0;i<2;i++){
     line(l+4+i,t+4+i,r-3-i,t+4+i);/*up-*/
     line(l+4+i,t+4+i,l+4+i,b-4-i);/*left|*/
     line(l+4+i,b-5+i,r-5+i,b-5+i);/*bottom-*/
     line(r-5+i,t+6-i,r-5+i,b-5+i);/*right|*/
     setcolor(15);
     }
   mouse_on();
   return(OK);
      default:   /* 如非上述情况,则frame参数作为边框的宽度 */
   frame_thick=frame;
      }         /* switch end */
  color1=(status==BUTTON_UP)?15:8;
  color2=(status==BUTTON_UP)?8:15;
  FillBar(l+1,t+1,r-1,b-1,SOLID_FILL,bc);
  mouse_off();
  for(i=0;i<frame_thick;i++){
     setcolor(color1);
     line(l,t+i,r-i,t+i);/*-*/ line(l+i,t,l+i,b-i);/*|*/
     setcolor(color2);
     line(l+i,b-i,r,b-i);/*-*/ line(r-i,t+i,r-i,b);/*|*/
     }
  mouse_on();
}       /* function end */

void OutTextEx(int x,int y,int bkground,int color,unsigned char *hz)
{
  FillBar(x,y,x+strlen(hz)*8,y+16,SOLID_FILL,bkground);
  mouse_off();
  OutText(x,y,color,hz);
  mouse_on();
}

/* 直接写屏 & XMS字库读取技术显示字符串 */
void OutText(int x,int y,unsigned char color,unsigned char *hz)
{  long i;
   char far *ptr;
   SHORT movebit,ybit;
   struct xms_move block;
   struct viewporttype v;
   UBYTE by[32],by1,by2,byte1,byte2,bm;
   getviewsettings(&v);
   x+=v.left; y+=v.top; /* 考虑到有可能设置了一个非全屏幕的视 */
   if( x<0 || y<0 || x>=639 || y>=479 || x>=v.right || y>=v.bottom ) return;
   ybit= y+15>=v.bottom?v.bottom-y:16; /* 使Y坐标不超过视的下边界 */
   ybit= ybit<=0?0:ybit;
   /* 采用写方式2 */
   outportb(0x3ce,5); outportb(0x3cf,2);
   /* 一次写4个位平面 */
   outportb(0x3c4,2);   outportb(0x3c5,255);
   outportb(0x3ce,8);
   while(*hz){
     byte1=(UBYTE)*hz;  byte2=(UBYTE)*(hz+1);
     if( (byte1>=0xa1 && byte1<=0xfe) && (byte2>=0xa1 && byte2<=0xfe) ){
       UBYTE *byptr=by;
       if(x+15>v.right) break;         /* 超出视区不显示 */
       i=(byte1-0xa1)*94+byte2-0xa1;
       i<<=5;
       block.destination_handle=0;  /* 将汉字点阵数据从扩充内存移至数组中 */
       block.source_handle=xms_hzk16;
       block.destination_offset=(long)MK_FP(_DS,by); /* _DS用于小模式 */
       block.source_offset=i;
       block.byte_count=32;
       xms_movedata( &block );
       /* 因为一个字节含有8个像点,必须考虑到起始位置未处于x%8==0时的情况 */
       /* 为此设置一个只从有效的x位置写起的偏移量movebit */
       movebit=x%8;   /* 起始位置在缓冲区中字节内相对偏移 */
       for( i=0;i<ybit;i++ ){
         ptr=MK_FP( 0xA000,(y+i)*80+x/8 );
  by1=*byptr++; by2=*byptr++;
  /* 将汉字点阵的两个字节写入缓冲区 */
  /* the first byte */
  /* 要写8个像点的掩码,此掩码即为汉字的点阵信息,第一个字节 */
         outportb( 0x3cf,by1>>movebit );
  bm=*ptr;
  *ptr++=color;  /* 将颜色值写入缓冲区 */
  /* the second byte */
  outportb( 0x3cf,(by1<<(8-movebit))|(by2>>movebit) );
  /* 要写8个像点的掩码,第二个字节 */
  bm=*ptr;
  *ptr++=color;
  /* the third byte,if movebit==0 not write */
  if( movebit!=0 ){
           /* 要写8个像点的掩码 */
    outportb( 0x3cf,by2<<(8-movebit) );
    bm=*ptr;
    *ptr=color;
    }
  } /* 显示汉字end */
       x+=16;       hz+=2;
       }
     else{
 if(x+7>v.right) break;         /* 超出视,则不显示 */
 block.destination_handle=0;  /* 将汉字点阵数据从扩充内存移至数组中 */
 block.source_handle=xms_asc16;
 block.destination_offset=(long)MK_FP(_DS,by); /* _DS用于小模式 */
 block.source_offset=byte1*16;
 block.byte_count=16;
 xms_movedata( &block );
 movebit=x%8;   /* 起始位置在缓冲区中字节内相对位移 */
 for(i=0;i<ybit;i++){
   ptr=MK_FP( 0xA000,(y+i)*80+x/8 );
   by1=*(by+i);
   outportb( 0x3cf,by1>>movebit );
   bm=*ptr;
   *ptr++=color;
   if( movebit!=0 ){
     outportb( 0x3cf,by1<<(8-movebit) );
     bm=*ptr;
     *ptr++=color;
     }
          } /* for end */
        x+=8;   hz++;
 }       /* if ascii end */
     }          /* while end */
   bm=bm;
   outportb(0x3ce,8);   outportb(0x3cf,255);
   /* 缓冲区中每个字节的8位全部允许写 */
   outportb(0x3ce,5);   outportb(0x3cf,0);
}

BOOL load_hzk16_2_xms()
{  FILE *fp,*fp1; /* 装载hzk16进扩充内存,需要一个已分配足够大容量的句柄 */
   struct SREGS sregs;
   struct xms_move block;
   long string_length;
   long char_count=0L;
   if( (fp=fopen("hzk16","rb"))==NULL )       return(ERROR);
   if( (fp1=fopen("asc16","rb"))==NULL ){
     fclose(fp);
     return(ERROR);
     }
   while( (string_length=fread(xms_2_basemem_buffer,1,XMS_BUF,fp))!=0 ){
      block.byte_count=string_length;  /* 实际读到的字节数 */
      block.source_handle=0;
      block.source_offset=(long)MK_FP(_DS,xms_2_basemem_buffer);
      block.destination_handle=xms_hzk16;  /* xms内存句柄 */
      block.destination_offset=char_count;  /* 在扩充内存中的偏移量 */
      char_count+=string_length; /* 修正偏移量 */
      if( xms_movedata( &block )==ERROR ){
 fclose(fp);
        xms_free(xms_hzk16);
 return(ERROR);
 }
      }  /* while end */
   fclose(fp);
   while( (string_length=fread(xms_2_basemem_buffer,1,XMS_BUF,fp1))!=0 ){
      block.byte_count=4096;  /* 实际读到的字节数 */
      block.source_handle=0;
      block.source_offset=(long)MK_FP(_DS,xms_2_basemem_buffer);
      block.destination_handle=xms_asc16;  /* xms内存句柄 */
      block.destination_offset=0;  /* 在扩充内存中的偏移量 */
      if( xms_movedata( &block )==ERROR ){
 fclose(fp1);
 xms_free(xms_asc16);
 return(ERROR);
 }
      }  /* while end */
   fclose(fp1);
   return(OK);
}


BOOL BackupWin(int l,int t,int r,int b,int *block,int imageblock[]);
BOOL BackupWin(int l,int t,int r,int b,int *block,int imageblock[])
/* 参数:边界及将界面分成的块数blocks,*imageblock是希望得到一个指向xms内存/
   屏幕数据句柄的变量地址 */
{  struct xms_move xms_block;
   int i,block_num,high,block_high;  /* high每个分区块的高度 */
   long total_size,block_size[XMS_BLOCK_NUM];
   int handle;  /* 一个临时句柄 */
   high=b-t;
   total_size=imagesize(l,t,r,b);
/*  因为 imagesize() 无法计算大于64K的位图,这里根据这个函数的原理计算之 */
   if( total_size>65534 ) total_size=(long)((float)(r-l)*high/2.0+41);
   for(i=1;i<=XMS_BLOCK_NUM;i++)
     if( (float)total_size/(float)i < XMS_BUF ){
       *block=block_num=i; break; }
   for( i=0,block_high=high/block_num;i<block_num;i++ ){
     if(i==block_num-1)   block_high=high-block_high*(block_num-1);
     block_size[i]=imagesize(l,t,r,t+block_high);
     mouse_off();
     getimage(l,t,r,t+block_high,xms_2_basemem_buffer);
     mouse_on();
     t+=block_high;
     handle=xms_malloc( block_size[i]/1024+1 );
     imageblock[i]=handle;
     xms_block.byte_count=block_size[i];
     xms_block.source_handle=0;
     xms_block.source_offset=(long)MK_FP(_DS,xms_2_basemem_buffer);
     xms_block.destination_handle=handle;
     xms_block.destination_offset=0;
     if( xms_movedata( &xms_block )==ERROR ){
 xms_free(handle);
 return(ERROR);     }
     }  /* for end */
   return(OK);
}

BOOL RestoreWin(int l,int t,int r,int b,int block,int imageblock[]);
BOOL RestoreWin(int l,int t,int r,int b,int block,int imageblock[])
/* 参数:边界及将界面分成的块数block,*imageblock是希望得到一个指向xms内存/
   屏幕数据句柄的变量地址 */
{  struct xms_move xms_block;
   int i,high,block_high;  /* high每个分区块的高度 */
   long block_size[XMS_BLOCK_NUM];
   high=b-t;  r=r;
   for( i=0,block_high=high/block;i<block;i++ ){
     if(i==block-1)   block_high=high-block_high*(block-1);
     block_size[i]=imagesize(l,t,r,t+block_high);
     xms_block.byte_count=block_size[i];
     xms_block.source_handle=imageblock[i];
     xms_block.source_offset=0;
     xms_block.destination_handle=0;
     xms_block.destination_offset=(long)MK_FP(_DS,xms_2_basemem_buffer);
     if( xms_movedata( &xms_block )==ERROR ){
       xms_free(imageblock[i]);
       return(ERROR);
       }
     mouse_off();
     putimage(l,t,xms_2_basemem_buffer,COPY_PUT);
     mouse_on();
     xms_free(imageblock[i]);
     t+=block_high;
     }  /* for end */
   return(OK);
}

/* ...菜单函数对返回值的处理: 收到MENU_CLOSE时,关闭自己,关返回OK;  */
/*    收到MENU_NOT_CLOSE时continu.收到MENU_CLOSE_ALL时关闭自己,关且返回 */
/*    MENU_CLOSE_ALL */
/* ...菜单函数:只返回OK(当正常结束时),MENU_CLOSE_ALL(当要求所有菜单全关闭时 */
/* ...调用菜单的函数:当菜单返回OK时,由其决定父菜单的关闭与否,返回MENU_CLOSE*/
/*    或MENU_NOT_CLOSE;当菜单返回MENU_CLOSE_ALL,本身也返回MENU_CLOSE_ALL */
int PopMenu(struct CMenu (*m))
{
  int how_to_do, mx, my, redraw=1 ;
  int oldchoice, newchoice, left,top,right, bottom;
  int width=0, i, n, y;
  ClearKeyBuffer();
  if( (*m).frame==NULL_FRAME )  redraw=0; /* this is for NULL_FRAME */
  for(i=0,n=0;i<MAX_MENU_TITLE;i++){
    if( ((*m).inf[i].info)!=NULL ) n++;
    else break;
    }
  for(i=0;i<n;i++)
     width=Max( strlen((*m).inf[i].info),width );
  width*=8;
  left=(*m).left+6;
  top=(*m).top+8;
  right=(*m).left+width+6;
  bottom=(*m).top+(n+1)*16-8;
  if( (*m).left<0 || (*m).top<0 || ((*m).left+width+12)>639 || ((*m).top+(n+1)*16)>479 ){
    SystemError.str1="[PopMenu]菜单坐标不合法";
    SystemError.str2="坐标应该处在屏幕范围之内";
    MessageBox( &SystemError );
    return(ERROR);
    }
  if( BackupWin(left-6,top-8,right+6,bottom+8,&(*m).BackImageBlockNum,(*m).SaveBackImage)==ERROR){
    SystemError.str1="[PopMenu]无足够内存创建菜单,如果经常出现";
    SystemError.str2="此种现象,请与王家宝联系.";
    MessageBox( &SystemError );
    return(ERROR);
    }
  WinMake(left-6,top-8,right+6,bottom+8,MENU_BACKGROUND,(*m).frame,BUTTON_UP);
  mouse_off();
  for(i=0,y=top;i<n;i++,y+=16){
       if( (*m).inf[i].info[0]=='-' ){
  setcolor(DARKGRAY); line(left+7,y+8,right-9,y+8);
  setcolor(WHITE);    line(left+8,y+9,right-8,y+9);
  continue;
  }              /* draw a line end */
       OutText(left,y,MENU_TEXT_COLOR,(*m).inf[i].info);
       }   /* for end */
  mouse_on();
  if( redraw ){
    FillBar(left,top,right,top+16,SOLID_FILL,MENU_CHOICE_BACKGROUND);
    mouse_off();
    OutText(left,top,MENU_CHOICE_TEXT_COLOR,(*m).inf[0].info);
    mouse_on();
    }
  else{
    mouse_off();
    OutText(left,top,MENU_CHOICE_TEXT_COLOR,(*m).inf[0].info);
    mouse_on();
    }
  oldchoice=newchoice=0;
A: for(;;){
   if(MOUSE_MOVED){
     MOUSE_MOVED=0;
     mx=CMX;  my=CMY;
     if( mx>left && mx<right && my>top && my<bottom ){
       newchoice=(my-top)/16;
       if(newchoice!=oldchoice){
  if( (*m).inf[newchoice].info[0]!='-' ){
    if( redraw ){
      FillBar(left,oldchoice*16+top,right,oldchoice*16+top+16,SOLID_FILL,MENU_BACKGROUND);
      mouse_off();
      OutText(left,oldchoice*16+top,MENU_TEXT_COLOR,(*m).inf[oldchoice].info);
      mouse_on();
      FillBar(left,newchoice*16+top,right,newchoice*16+top+16,SOLID_FILL,MENU_CHOICE_BACKGROUND);
      mouse_off();
      OutText(left,newchoice*16+top,MENU_CHOICE_TEXT_COLOR,(*m).inf[newchoice].info);
      mouse_on();
      }
    else{
      mouse_off();
      OutText(left,oldchoice*16+top,MENU_TEXT_COLOR,(*m).inf[oldchoice].info);
      OutText(left,newchoice*16+top,MENU_CHOICE_TEXT_COLOR,(*m).inf[newchoice].info);
      mouse_on();
      }
    oldchoice=newchoice;
    }
  /* 使提示信息随着光条的移动而改变 */
  }
       }      /* if mouse in menu end */
     }        /* cursor end */
   if(RBUTTON_DOWN){
     RBUTTON_DOWN=0;
     RestoreWin(left-6,top-8,right+6,bottom+8,(*m).BackImageBlockNum,/
           (*m).SaveBackImage);
     return(OK);
     }
   if(LBUTTON_DOWN){   /* 如击左键在菜单内则调用函数进行处理 */
    LBUTTON_DOWN=0;
    mx=CMX;  my=CMY;
    if( InBar(mx,my,left,top,right,bottom-1) ){
     if( (*m).inf[(my-top)/16].info[0]!='-' ){
      if( redraw ){
 FillBar(left,oldchoice*16+top,right,oldchoice*16+top+16,SOLID_FILL,MENU_BACKGROUND);
 mouse_off();
 OutText(left,oldchoice*16+top,MENU_TEXT_COLOR,(*m).inf[oldchoice].info);
 mouse_on();
 }
      else{
 mouse_off();
 OutText(left,oldchoice*16+top,MENU_TEXT_COLOR,(*m).inf[oldchoice].info);
 mouse_on();
 }
      oldchoice=(my-top)/16;
      if( redraw ){
 FillBar(left,oldchoice*16+top,right,oldchoice*16+top+16,SOLID_FILL,MENU_CHOICE_BACKGROUND);
 mouse_off();
 OutText(left,oldchoice*16+top,MENU_CHOICE_TEXT_COLOR,(*m).inf[oldchoice].info);
 mouse_on();
 }
      else{
 mouse_off();
 OutText(left,oldchoice*16+top,MENU_CHOICE_TEXT_COLOR,(*m).inf[oldchoice].info);
 mouse_on();
 }
KEYENTER:
      how_to_do=(*(*m).inf[oldchoice].function)();
      switch( how_to_do ){
 case MENU_CLOSE:
EXIT:
   RestoreWin(left-6,top-8,right+6,bottom+8,(*m).BackImageBlockNum,/
           (*m).SaveBackImage);
   return(OK);
 case MENU_NOT_CLOSE:
   MOUSE_MOVED=1;
   LBUTTON_DOWN=0;
   how_to_do=MENU_NOT_CLOSE;       /* 被指示保持打开状态 */
   goto A;
 case MENU_CLOSE_ALL:
   RestoreWin(left-6,top-8,right+6,bottom+8,(*m).BackImageBlockNum,/
           (*m).SaveBackImage);
   LBUTTON_DOWN=0;
   return(MENU_CLOSE_ALL);
 default:                  /* perhpers the function is null() */
   how_to_do=MENU_NOT_CLOSE;
   continue;
   }  /* switch end */
 }      /* if lbutton in menu end */
       }
      else{  /* press lbutton out of menu coords,close the menu */
 RestoreWin(left-6,top-8,right+6,bottom+8,(*m).BackImageBlockNum,/
           (*m).SaveBackImage);
 return(OK);
 }
    }        /* if button down end */
   if( Kbhit() ){
     int kbcode;
     if( (kbcode=GetKey())==ENTER ) goto KEYENTER;
     if( kbcode==ESC ) goto EXIT;
     }
   }          /* for end */
}               /* function end */

BOOL InitDialog(struct CDialog *bm)
{  int l,t,r,b,i;       /* the frame coords of menu */
   if((*bm).left<0 || (*bm).top<0 || (*bm).right>639 || (*bm).bottom>479){
     SystemError.str1="[InitDialog]对话框坐标不合法";
     SystemError.str2="坐标应该处在屏幕范围之内";
     MessageBox( &SystemError );
     return(ERROR);
     }
   l=(*bm).left;   t=(*bm).top;    r=(*bm).right;     b=(*bm).bottom;
   if( r-l>=639 && b-t>=479 ) (*bm).move=0;
   if( BackupWin(l,t,r,b,&(*bm).BackImageBlockNum, (*bm).SaveDialogBack)==ERROR){
     SystemError.str1="[InitDialog]无足够内存创建对话框,如果经常出现";
     SystemError.str2="此种现象,请与王家宝联系.";
     MessageBox( &SystemError );
     return(ERROR);
     }
   WinMake(l,t,r,b,MENU_BACKGROUND,STD_FRAME,BUTTON_UP);
   FillBar( l+4,t+4,r-4,t+20 ,SOLID_FILL,LIGHTBLUE );
   setviewport(l+4,0,r-((*bm).close?20:4),479,1);
   mouse_off();
   OutText(0,(*bm).top+5,WHITE,(*bm).title); /* 写标题 */
   mouse_on();
   setviewport(0,0,639,479,1);
   if( (*bm).close )   /* 判断是否显示关闭按钮 */
     Button( (*bm).right-20,(*bm).top+4,NULL,"x",BUTTON_UP);
   (*bm).active=1;  /* 应用于无模式对话框 */
   (*(*bm).draw)(*bm);  /* 可以初始化客户区 */
}

int RunDialog( struct CDialog *bm )
{
  int x,y,distx,disty,mx,my;
  int ol,ot,or,ob,nl,nt,nr,nb;
  int once_in_title=0,return_value=DIALOG_CLOSE;
  if( !(*bm).active )    return(OK);
  nl=ol=(*bm).left; nt=ot=(*bm).top;
  nr=or=(*bm).right;       nb=ob=(*bm).bottom;
  while( 1 ){
   if( LBUTTON_DOWN ){

    mx=CMX; my=CMY;
    if( InBar(mx,my,(*bm).right-20,(*bm).top+4,(*bm).right-4,/
  /* 如果按了关闭按钮 */   (*bm).top+20) && (*bm).close ){
      if( ActionButton((*bm).right-20,(*bm).top+4,NULL,"x")==0 ) continue;
EXIT:
      RestoreWin(ol,ot,or,ob,(*bm).BackImageBlockNum,(*bm).SaveDialogBack);
      (*bm).active=0;
      reset_event_status();
      ClearKeyBuffer();
      return(return_value);
      }           /* if pressed X button end */
    if( InBar(mx,my,(*bm).left+4,(*bm).top+4,(*bm).right-((*bm).close?20:4),(*bm).top+20) &&/
       (*bm).move ){
  /* 在标题区内 */
      distx=mx-(*bm).left; disty=my-(*bm).top;       /* 设置mouse最大移动区 */
      set_mousex(distx,639-( (*bm).right-(*bm).left-distx ));
      set_mousey(disty,479-( (*bm).bottom-(*bm).top-disty ));
      setwritemode(XOR_PUT); setcolor(8);
      setlinestyle(0,0,3);
      mouse_off();
      rectangle(nl+1,nt+1,nr-1,nb-1);
      mouse_on();
      while( !LBUTTON_UP ){
      if( MOUSE_MOVED ){
 MOUSE_MOVED=0;
 x=CMX; y=CMY;
 mouse_off();
 rectangle(nl+1,nt+1,nr-1,nb-1);
 nl=x-distx;             nt=y-disty;
 nr=x-distx+(*bm).right-(*bm).left;
 nb=y-disty+(*bm).bottom-(*bm).top;
 rectangle(nl+1,nt+1,nr-1,nb-1);
 mouse_on();
 once_in_title=1;
 }       /* if mosue_moved end */
      }         /* while lbutton_down title bar end */
      set_mousex(1,639);  set_mousey(1,479);
      if( once_in_title ){
 mouse_off();
 rectangle(nl+1,nt+1,nr-1,nb-1);
 mouse_on();
 }
      setlinestyle(0,0,1);
      if( LBUTTON_UP ){ /* 松开左键结束移动,则将框移至新区域 */
 reset_event_status();
 if( ot==nt && ol==nl ){/* if new positon==old position do nothing */}
 else{
   BackupWin(ol,ot,or,ob,&(*bm).BackImageBlockNum,(*bm).SaveDialogImage);
   RestoreWin(ol,ot,or,ob,(*bm).BackImageBlockNum,(*bm).SaveDialogBack);
   BackupWin(nl,nt,nr,nb,&(*bm).BackImageBlockNum,(*bm).SaveDialogBack);
   RestoreWin(nl,nt,nr,nb,(*bm).BackImageBlockNum,(*bm).SaveDialogImage);
   ol=nl; ot=nt; or=nr; ob=nb;
   }
 (*bm).left=ol;  (*bm).top=ot; /* 保存新坐标 */
 (*bm).right=or;  (*bm).bottom=ob;
 setlinestyle(0,0,1);
 setwritemode(COPY_PUT);
 }
      continue;
      }             /* if pressed title bar end */
    setwritemode(COPY_PUT);
    setlinestyle(0,0,1);
    ClearKeyBuffer();
    if( InBar(mx,my,(*bm).left+2,(*bm).top+22,(*bm).right-2,(*bm).bottom-2) )
      if( (*(*bm).react)( mx, my, *bm, &return_value )==DIALOG_CLOSE )
   goto EXIT;/* 如左键点在框内,则调用响应函数 */
    LBUTTON_DOWN=0;
    continue;
    } /* if lbutton_down end */
  if( Kbhit() ){
    mx=my=-1;
    if( (*(*bm).react)( mx, my, (*bm), &return_value )==DIALOG_CLOSE )
   goto EXIT;
    ClearKeyBuffer();
    continue;
    }
  } /* while end */
}               /* function end */

BOOL Button(int gl,int gt,char *btn_str,char *style,int status)
{
   char kind,*p,*str[]={"确认","取消","开始 Start"};
   int width, height, gr, gb, i, x, y, which_arrow,addbits;
   static int arrow[][8]={ 0x10,0x38,0x7c,0xfe,0x38,0x38,0x38,0x00,
      0x00,0x38,0x38,0x38,0xfe,0x7c,0x38,0x10
      };
    /* arrow数组0为向上的,1为向下的 */
   if( gl<0 || gt<0 ) return(ERROR);
   switch( (kind=toupper(style[0])) ){
      case 'X':      /* exit btn */
      case 'U': width=X_BTN_W; height=X_BTN_H;  /* up arrow btn */
  which_arrow=0;  break;
      case 'D': width=X_BTN_W; height=X_BTN_H;  /* down arrow btn */
  which_arrow=1;  break;
      case 'C':      /* check */
      case 'R': width=CBtn_W;  height=CBtn_H; /* radio */
  p=NULL; break;
      case 'Y': width=NORMAL_BTN_W; height=NORMAL_BTN_H; /* yes btn */
  p=str[0];       break;
      case 'N': width=NORMAL_BTN_W; height=NORMAL_BTN_H; /* no btn */
  p=str[1];       break;
      case 'S': width=100;  height=23;  /* start btn*/
  p=str[2];       break;
      default:  width=NORMAL_BTN_W; height=NORMAL_BTN_H;
  p=btn_str;
      }
   gr=gl+width;         gb=gt+height;
   WinMake(gl+1,gt+1,gr-1,gb-1,7,BUTTON_FRAME,status);
   if( kind=='U' || kind=='D' ){ /* 画箭头 */
      if(status==BUTTON_UP) addbits=0;
      else addbits=1;  /* 使其被向里按 */
      mouse_off();
      for(y=0;y<8;y++)
 for(x=0;x<8;x++)
    if( (arrow[which_arrow][y]>>(7-x)) &1 )
        putpixel(gl+5+x+addbits,gt+5+y,BLACK);
      mouse_on();
      return(OK);
      }  /* if 'u' || 'd' end */
   if( kind=='X' ){ /* 画关闭按钮 */
     if(status==BUTTON_UP) addbits=0;
     else addbits=1;  /* 使其被向里按 */
     mouse_off();
     for(i=0;i<2;i++){
       setcolor(0);
       line(gl+4+addbits,gt+4+i,gr-4+addbits,gb-4+i);   /* / */
       line(gr-4+addbits,gt+4+i,gl+4+addbits,gb-4+i);   /* / */
       }
      mouse_on();
      return(OK);
      }  /* if end */
    i=gl+(int)(width/2.0-(strlen(p)/2.0)*8);
    mouse_off();
    setcolor(BLACK);       /* 给按钮加个框 */
    rectangle(gl,gt,gr,gb);
    OutText(i+(status==BUTTON_UP?0:1),gt+5,style[1]==0?BTN_TEXT_COLOR:8,p);
    mouse_on();
    return(OK);
}

BOOL ActionButton(int l,int t,char *btn_str,char *style)
{
  int width,height,r,b,x,y;
  if( LBUTTON_DOWN ) LBUTTON_UP=0;
  Button( l,t,btn_str,style,!BUTTON_UP);
  switch( toupper(style[0]) ){
      case 'S': width=100;  height=23; /* start btn*/
  break;
      case 'X':      /* exit btn */
      case 'U':      /* up arrow btn */
      case 'D': width=X_BTN_W; height=X_BTN_H;  /* down arrow btn */
  break;
      case 'C':      /* check */
      case 'R': width=CBtn_W;  height=CBtn_H; /* radio */
  break;
      case 'Y':      /* yes btn */
      case 'N':      /* no btn */
      default:  width=NORMAL_BTN_W; height=NORMAL_BTN_H;
      }
  r=l+width;         b=t+height;
  while( !LBUTTON_UP ) ;
  LBUTTON_UP=0;
  x=CMX; y=CMY;
  Button( l,t,btn_str,style,BUTTON_UP);
  return( InBar(x,y,l,t,r,b) );
}

int MessageBox(struct CMessageBox *w)
{  int x,y,which,i,return_value,x_width,y_width,max_str;
   char whichchar;
   struct CDialog bm;
   x_width=(NORMAL_BTN_W+6)*(*w).style+16;
   y_width=NORMAL_BTN_H+76;
   max_str=Max( strlen((*w).str1),strlen((*w).str2) );
   x_width=Max( x_width,max_str*8+8 );
   if( x_width>639 ) ;
   bm.title=(*w).title;
   msg_btn_num=(*w).style;
   bm.left=319-x_width/2; bm.top=239-y_width/2;
   bm.right=319+x_width/2;;     bm.bottom=239+y_width/2;
   bm.close=(*w).close; bm.move=(*w).move;
   msgbox_str1=(*w).str1;
   msgbox_str2=(*w).str2;
   bm.draw=gMessageBoxDraw; bm.react=gMessageBoxReact;
   for(i=msg_btn_num;i>0;i--){
     msg_btn[msg_btn_num-i][0]=2+(NORMAL_BTN_W+6)*i;
     msg_btn[msg_btn_num-i][1]=6+NORMAL_BTN_H;
     }
   if( InitDialog(&bm)==ERROR)
      return(ERROR);
   return( RunDialog( &bm ) );
}

static int gMessageBoxDraw(struct CDialog bm)
{ int i;
  char *which_btn[]={"y","n"};
  setviewport(bm.left,bm.top+22,bm.right,bm.bottom,1);
  mouse_off();
  OutText( 6,6,MENU_TEXT_COLOR,msgbox_str1 );
  OutText( 6,26,MENU_TEXT_COLOR,msgbox_str2 );
  mouse_on();
  setviewport(0,0,639,479,1);
  for(i=0;i<msg_btn_num;i++)
    if( msg_btn[i][0]>0 )   /* 条件显示2个按钮,顺序为y,n  */
      Button( bm.right-msg_btn[i][0],bm.bottom-msg_btn[i][1],NULL,which_btn[i],BUTTON_UP);
}

int gMessageBoxReact(int x,int y,struct CDialog bm ,int *return_value)
{ /* the funcion return whether Dialog close,
 return_value tell RunDialog the function what had done */
  int which,tmp_btn[2][2],pressed=0,key;
  char *whichchar[]={"y","n"};
  for(which=0;which<msg_btn_num;which++){
    tmp_btn[which][0]=bm.right-msg_btn[which][0];
    tmp_btn[which][1]=bm.bottom-msg_btn[which][1];
    }
  for(which=0;which<msg_btn_num;which++) /* 判断哪个按钮被按了 */
    if(InBar(x,y,tmp_btn[which][0],tmp_btn[which][1],tmp_btn[which][0]+/
     NORMAL_BTN_W,tmp_btn[which][1]+NORMAL_BTN_H) ){
      pressed=1;
      break;
      }
  if( pressed ){
     if( !ActionButton(tmp_btn[which][0],tmp_btn[which][1],NULL,whichchar[which]) )
       return(DIALOG_NOT_CLOSE);
     *return_value=which;
KEYPRESS:
     return(DIALOG_CLOSE);
     }
  if( Kbhit() ){
    if( (key=GetKey())==ENTER ){ *return_value=0; pressed=1; goto KEYPRESS ; }
    if( key==ESC && msg_btn_num==2 ){ *return_value=1; pressed=1; goto KEYPRESS ; }
    }
}

int GetBtnStatus(int groupnum,int member,struct CButton btn[])
{ int i,num;
  if( btn[groupnum].style==CHECK ) /* check */
    return( btn[groupnum].status[member] );
  else{     /* radio */
    num=btn[groupnum].num;
    for(i=0;i<num;i++)
      if( btn[groupnum].status[i] ) return( i );
    }
}

void InitBtn(int group,struct CButton btn[],struct CDialog bm)
{ int i,j,l,t;
  GROUPS=group;
  mouse_off();
  for(i=0;i<group;i++)
   for(j=0;j<btn[i].num;j++){
     l=bm.left+btn[i].btncoord[j][0]+4; t=bm.top+22+btn[i].btncoord[j][1]+4;
     if( btn[i].style==CHECK ){
       WinMake(l,t,l+CBtn_W,t+CBtn_H,MENU_BACKGROUND,BUTTON_FRAME,!BUTTON_UP);
       if( btn[i].status[j] )
  OutText(l+1,t-4,0,"x");
       }
     else
       CreatRadioBtn(l+CBtn_W/2,t+CBtn_H/2,!btn[i].status[j]);
     OutText(l+CBtn_W+4,t-4,MENU_TEXT_COLOR,btn[i].btntip[j]);
     }
  mouse_on();
}

void CreatRadioBtn(int ox,int oy,int status)
{
  int colorcircle;
  colorcircle=(status==BUTTON_UP)?MENU_BACKGROUND:BLACK;
  setcolor(8);
  setfillstyle(SOLID_FILL,MENU_BACKGROUND);
  mouse_off();
  fillellipse(ox,oy,CBtn_W-4,CBtn_H-4);
  if( status!=BUTTON_UP ){
    setfillstyle(SOLID_FILL,colorcircle);
    fillellipse(ox,oy,CBtn_W-6,CBtn_H-6);
    }
  mouse_on();
}

int BtnReact(int x,int y,struct CButton btn[],struct CDialog bm)
{
 int i,j,k,l,t;
 for(i=0;i<GROUPS;i++)
   for(j=0;j<btn[i].num;j++){
     l=bm.left+btn[i].btncoord[j][0]+4; t=bm.top+22+btn[i].btncoord[j][1]+4;
     if( InBar(x,y,l,t-4,l+CBtn_W+strlen(btn[i].btntip[j])*8,t+CBtn_H+12) ){
 /* 点中一个按钮 */
 if( btn[i].style==CHECK ){
   btn[i].status[j]=!btn[i].status[j];
   WinMake(l,t,l+CBtn_W,t+CBtn_H,MENU_BACKGROUND,BUTTON_FRAME,!BUTTON_UP);
   if( btn[i].status[j] ){
     mouse_off();
     OutText(l+1,t-4,0,"x");
     mouse_on();
     }
   return(OK);
   }
 if(btn[i].style==RADIO ){
   for(k=0;k<btn[i].num;k++)
     if( btn[i].status[k] && k!=j ){
       btn[i].status[k]=0;  btn[i].status[j]=1;
       l=bm.left+btn[i].btncoord[k][0]+4; t=bm.top+22+btn[i].btncoord[k][1]+4;
       CreatRadioBtn(l+CBtn_W/2,t+CBtn_H/2,BUTTON_UP);
       l=bm.left+btn[i].btncoord[j][0]+4; t=bm.top+22+btn[i].btncoord[j][1]+4;
       CreatRadioBtn(l+CBtn_W/2,t+CBtn_H/2,!BUTTON_UP);
       return(OK);
       }
   }    /* if radio end */
 } /* biggest if end */
     }  /* the second for end */
   return(OK);
}

int gEditField(int l,int t,int r,int b,int n,struct CEdit g[],int yes_x,/
    int yes_y,int no_x,int no_y,char *title)
/* n is howmany edit filed,the edit not have Date type */
/* only return 0 or 1,  0 is yes,  1 is no */
{  int  i, j, x, y, ld, c, p, show=1,mx, my, count;
   struct CDialog bm;
   ClearKeyBuffer();
   if( l<0 || t<0 || r>639 || b>479){
     SystemError.str1="[gEditField]函数EditField出错,边界超界";
     SystemError.str1=NULL;
     MessageBox( &SystemError );
     return(ERROR);
     }
   oldx=-8; oldy=-8;
   bm.title=title;
   bm.left=l;  bm.top=t;
   bm.right=r;     bm.bottom=b;
   bm.close=0;       bm.move=0;
   bm.draw=null; bm.react=null;
   if( InitDialog( &bm )==ERROR)   return(ERROR);  /* 初始化框 */
   if( yes_x>=0 )    Button(l+yes_x,t+22+yes_y,NULL,"y",BUTTON_UP);
   if( no_x>=0 ) Button(l+no_x,t+22+no_y,NULL,"n",BUTTON_UP);
   for(i=0;i<n;i++){
      mouse_off();
      OutText(l+g[i].sx,t+22+g[i].sy,g[i].color,g[i].s);
      mouse_on();
      WinMake(l+g[i].ex-1,t+22+g[i].ey-2,l+g[i].ex+1+g[i].w*8,t+22+g[i].ey+18,G_EDIT_FILL_COLOR,/
      BUTTON_FRAME,!BUTTON_UP);
      mouse_off();
      OutText(l+g[i].ex,t+22+g[i].ey-2,g[i].color,g[i].e);
      mouse_on();
      }                                 /* end for */
   ClearKeyBuffer();
   i=0;p=0;
#define CURS_TIME 7604
   CreateTimer(2,CURS_TIME);
   do{
     if( CheckTimeOut( CURS_TIME ) )
       Curs(l+g[i].ex+p*8,t+22+g[i].ey,(show=!show));
     if(LBUTTON_DOWN){
 LBUTTON_DOWN=0;
 mx=CMX;  my=CMY;
 if(InBar(mx,my,l+yes_x,t+22+yes_y,l+yes_x+NORMAL_BTN_W,t+22+yes_y+NORMAL_BTN_H)){
    if( ActionButton(l+yes_x,t+22+yes_y,NULL,"y")==0 ) continue;
EXITEDIT:
    RestoreWin( l,t,r,b+1,bm.BackImageBlockNum,bm.SaveDialogBack);
    ReleaseTimer(CURS_TIME);
    return(0);
    }
 if(InBar(mx,my,l+no_x,t+22+no_y,l+no_x+NORMAL_BTN_W,t+22+no_y+NORMAL_BTN_H)){
     if( ActionButton(l+no_x,t+22+no_y,NULL,"n")==0 ) continue;
     RestoreWin( l,t,r,b+1,bm.BackImageBlockNum,bm.SaveDialogBack);
            ReleaseTimer(CURS_TIME);
     return(1);
     }
 for(count=0;count<n;count++)    /*check whethe mouse press in editfiled*/
   if(InBar(mx,my,l+g[count].ex,t+22+g[count].ey,l+g[count].ex+g[count].w*8,/
       t+22+g[count].ey+16)){
       i=count;    p=0;
       break;
       }  /* if mouse in filed press end */
  } /* if LBUTTON_DOWN end */
     if( Kbhit() ){
 switch(c=GetKey()){
   case UP:
     if( i>0 ) i--;
     p=0;
     break;
   case DOWN:
     if( i<n-1 ) i++;
     p=0;
     break;
   case LEFT:
     if(p>0) p--;
     break;
   case RIGHT:
     if( p<g[i].w-1 && p<strlen(g[i].e)-1 ) p++;
     break;
   case ENTER:
     if( n==1 )  goto EXITEDIT;
     if( i<n-1 ) i++;
     p=0;
     break;
   case HOME:
     p=0;break;
   case END:
     p= strlen(g[i].e)==0?0:strlen(g[i].e)-1;
     break;
   case INS:
     insert=!insert;
     break;
   case BACKSPACE:
     if(p==0) break;
     if(toupper(g[i].p[0])=='N' && g[i].e[p-1]=='.'){
        p--;break;}
     if( toupper(g[i].p[0])=='N')
       g[i].e[p-1]=' ';         /* in the ' '=space */
     else{
       memmove(&g[i].e[p-1],&g[i].e[p],g[i].w-p);
       g[i].e[g[i].w-1]='/0';}   /* int the '_' */
     WinMake(l+g[i].ex-1,t+22+g[i].ey-2,l+g[i].ex+1+g[i].w*8,t+22+g[i].ey+18,G_EDIT_FILL_COLOR,/
         BUTTON_FRAME,!BUTTON_UP);
     mouse_off();
     OutText(l+g[i].ex,t+22+g[i].ey-2,g[i].color,g[i].e);
     mouse_on();
     p--;
     break;
   case DEL:
     if(toupper(g[i].p[0])=='N' && g[i].e[p]=='.')  break;
     if(g[i].w==1)  g[i].e[0]=NULL;
     else{
       if( toupper(g[i].p[0]=='N') )
  g[i].e[p]=' ';
       else{
  memmove(&g[i].e[p],&g[i].e[p+1],g[i].w-p);
  g[i].e[g[i].w-1]=NULL;  /* in the '_' */
  }
       }
     WinMake(l+g[i].ex-1,t+22+g[i].ey-2,l+g[i].ex+1+g[i].w*8,t+22+g[i].ey+18,G_EDIT_FILL_COLOR,/
         BUTTON_FRAME,!BUTTON_UP);
     mouse_off();
     OutText(l+g[i].ex,t+22+g[i].ey-2,g[i].color,g[i].e);
     mouse_on();
     break;
   case ESC:
   case PGUP:
   case PGDN:
   case TAB:
     continue;
   default:
     switch(toupper(g[i].p[0])){        /* the @ switch */
       case 'C':
  switch(toupper(g[i].p[1])){
    case 'N':
      if(!isdigit(c)) continue; break;
    case 'A':
      if(!isalpha(c)) continue; break;
    case 'B':
      if(!isalnum(c)) continue; break;
    }
  break;
       }                        /* the @ switch end */
     if(p<g[i].w){
       if(insert){
   switch(toupper(g[i].p[0])){
     case 'C':
       memmove(&g[i].e[p+1],&g[i].e[p],g[i].w-p-1);
       break;
     }
   }
       g[i].e[p]=c;
       WinMake(l+g[i].ex-1,t+22+g[i].ey-2,l+g[i].ex+1+g[i].w*8,t+22+g[i].ey+18,G_EDIT_FILL_COLOR,/
         BUTTON_FRAME,!BUTTON_UP);
       mouse_off();
       OutText(l+g[i].ex,t+22+g[i].ey-2,g[i].color,g[i].e);
       mouse_on();
       p++;
     }                          /* if(p<g[i].w) end */
     if(p==g[i].w)      p=g[i].w-1;
     }                          /* switch end */
   }   /* if kbhit end */
   }while(1);                    /* do while cycle end */
}

void Curs(int x, int y,int show)
{
    mouse_off();
    if(oldx!=x || oldy!=y){
 setcolor(G_EDIT_FILL_COLOR);
 line(oldx,oldy+16,oldx+8,oldy+16);        /* earse the old Curs */
 line(oldx,oldy+17,oldx+8,oldy+17);        /* earse the old Curs */
 }
    if( show ) setcolor(YELLOW);
    else setcolor(G_EDIT_FILL_COLOR);
    line(x,y+16,x+8,y+16);
    line(x,y+17,x+8,y+17);
    oldx=x;  oldy=y;
    mouse_on();
}

int Select(int wl,int wt,int wr,int wb,char *str[])
/* 窗口的坐标为图形的,凡涉及到实际作图函数的坐标的为图形的,否则为文本坐标,
窗口的坐标必须为 16 的倍数,
调用方法:
 char *str[]={"123", ... ,"dataEND122", "NULL" };数组必须以NULL结尾
 "NULL" is the end flag of select()
 传给此函数的str[]的最后一个*str必须为"NULL",it a string, not a '/0'
*/
{ int i,n,HScroll_height,HScroll_start;
  int w_old_ligter=0,w_ligter=0,w_height,str_end=-1,str_old_option=0,str_option=0;
/*  老的加亮的T ,此为加亮的T,窗口高度T,字串尾,将被擦除的老的选项,当前被选择的*/
  int need_draw=1,must_redraw=0,key,double_press=0;/* 是否重写WIN */
  char tmp[80];
  if( (wr-wl)/16<2 || (wb-wt)/16<3 || (wr-wl)%16 || (wb-wt)%16 || wl<0 || wt<0 || wr>639 || wb>479 || wl>=wr || wt>=wb ){
    SystemError.str1="[Select]列表选择函数的坐标不合法";
    SystemError.str2="宽与高应该为16倍数,并且坐标不应超出屏幕范围";
    MessageBox( &SystemError );
    return(NOSELECT);
    }
  while(  strcmp(strupr(strcpy(tmp,str[++str_end])),"NULL")!=0  );
  if( str_end==0 ) return(NOSTRING); /* No string can be select */
  w_height=(wb-wt)/16;  /* 计算窗口高度*/
  WinMake(wr-14,wt+16,wr,wb-16,7,BUTTON_FRAME,BUTTON_UP);
  Button(wr-15,wt,NULL,"U",BUTTON_UP);
  Button(wr-15,wb-16,NULL,"D",BUTTON_UP);
  wr-=16; /* left the scroll bar space */
  FillBar(wl,wt,wr,wb,SOLID_FILL,MENU_BACKGROUND);
  for(;;){
    if(need_draw){ /* 如果窗口不必重画,就略过,提高速度,防止闪烁 */
      for(i=0,n=str_option-w_ligter;i<w_height;i++,n++){  /*准备重画整个窗口*/
        setviewport(0,0,639,479,1);
 if( w_ligter==0 || w_ligter==w_height-1 || must_redraw ){ /*窗口必须滚动,其中的全部选项必须更新*/
   FillBar(wl,wt+i*16,wr,wt+(i+1)*16,SOLID_FILL,MENU_BACKGROUND);
   if( n<str_end && n>=0 ){ /*处理最后的选项不在窗口最下端的情况*/
     if( i>=str_end ) break;
     setviewport(wl,wt,wr,wb,1);
     mouse_off();
     OutText(0,i*16,MENU_TEXT_COLOR,str[n]);
     mouse_on();
     }
   } /* if end */
 else{ /*窗口不必滚动,只需让亮条移动即可,对旧亮条选项进行更新*/
   FillBar(wl,wt+w_old_ligter*16,wr,wt+(w_old_ligter+1)*16,SOLID_FILL,MENU_BACKGROUND);
   setviewport(wl,wt,wr,wb,1);
   mouse_off();
   OutText(0,w_old_ligter*16,MENU_TEXT_COLOR,str[str_old_option]);
   mouse_on();
   } /* else end */
        } /* for end */
      setviewport(0,0,639,479,1);
      /* 重画正在被选择的亮条 */
      FillBar(wl,wt+w_ligter*16,wr,wt+(w_ligter+1)*16,SOLID_FILL,MENU_CHOICE_BACKGROUND);
      setviewport(wl,wt,wr,wb,1);
      mouse_off();
      OutText(0,w_ligter*16,MENU_CHOICE_TEXT_COLOR,str[str_option]);
      mouse_on();
      /* 更新显示进度条 */
      setviewport(0,0,639,479,1);
      if(str_end>w_height){
 HScroll_height=(int)((float)(wb-wt-32)/(float)str_end*(float)w_height);
 HScroll_start=(int)((float)(wb-HScroll_height-wt-32)/(float)(str_end-1)*(float)str_option);
 FillBar(wr+1,wt+16,wr+16,wt+16+HScroll_start,SOLID_FILL,7);
 FillBar(wr+1,wt+16+HScroll_height+HScroll_start,wr+16,wb-16,SOLID_FILL,7);
 WinMake(wr+2,wt+16+HScroll_start,wr+16,wt+16+HScroll_start+HScroll_height,7,BUTTON_FRAME,BUTTON_UP);
 }       /* if end */
      }  /* if end */
    if( double_press ) return(str_option);
    need_draw=0;
    if( LBUTTON_DOWN ){
      int tmpx,tmpy;
      tmpx=CMX; tmpy=CMY;
      if( InBar(tmpx,tmpy,wl+1,wt+1,wr-1,wb-1) ){
        int press_postion=(tmpy-wt)/16;
 if( str_option+press_postion-w_ligter>str_end-1 ){
   LBUTTON_DOWN=0; /* here is where >maxstrings,no react */
   continue;
   }
 w_old_ligter=w_ligter; str_old_option=str_option;
 w_ligter=press_postion; str_option+=press_postion-w_old_ligter;
 need_draw=1;
 if( get_double_press() )
   double_press=1;
 LBUTTON_DOWN=0;
 continue;
 } /* press in test window end */
      if( InBar(tmpx,tmpy,wr+1,wt+1,wr+15,wt+15) ){
 if( !ActionButton(wr+1,wt,NULL,"u") ) continue;
 need_draw=1;  key=UP;
        reset_event_status();
 goto MOUSE_OPERATION;
 }
      if( InBar(tmpx,tmpy,wr+1,wt+17,wr+15,wt+17+HScroll_start) ){
 need_draw=1;  key=PGUP;
        reset_event_status();
 goto MOUSE_OPERATION;
 }
      if( InBar(tmpx,tmpy,wr+1,wt+17+HScroll_height+HScroll_start,wr+15,wb-17) ){
 need_draw=1;  key=PGDN;
 reset_event_status();
 goto MOUSE_OPERATION;
 }
      if( InBar(tmpx,tmpy,wr+1,wb-15,wr+15,wb-1) ){
 if( !ActionButton(wr+1,wb-16,NULL,"d") ) continue;
 need_draw=1;  key=DOWN;
        reset_event_status();
 goto MOUSE_OPERATION;
 }
      LBUTTON_DOWN=0;
      }  /* lbtn_down end */
    if( Kbhit() ){
      need_draw=1;
      key=GetKey();
MOUSE_OPERATION:
      switch( key ){
 case UP:if( str_end>0 ){
    if( str_option==0 ){ need_draw=0; break; }
    if(w_ligter>=0){ /* 如果亮条未到达上边界*/
      w_old_ligter=w_ligter;
      if( w_ligter>0 ) w_ligter--;
      str_old_option=str_option--;
      break;
      }
    } /* if str_end>0 end */
    break;
 case DOWN:if( str_end>0 ){
      if(str_option==str_end-1){ need_draw=0; break; }
      if(w_ligter<=w_height-1){
        w_old_ligter=w_ligter;
        if( w_ligter<w_height-1 ) w_ligter++;
        str_old_option=str_option++;
        break;
        }
      } /* str_end >0 end */
    break;
 case HOME:if(str_end>0){
      if( str_option==0 ){ need_draw=0; break; }
      str_old_option=str_option;
      str_option=0;
      w_old_ligter=w_ligter;
      w_ligter=0;
      }
    break;
 case END: if(str_end>0){
      if( str_option==str_end-1 ){ need_draw=0; break; }
      str_old_option=str_option;
      str_option=str_end-1;
      w_old_ligter=w_ligter;
      if( str_end<w_height )
        w_ligter=str_end-1;
      else
        w_ligter=w_height-1;
      }
    break;
 case PGUP:if(str_end>0){
      if( str_option==0 ){ need_draw=0 ; break; }
      must_redraw=1;
      str_old_option=str_option;
      w_old_ligter=w_ligter;
      if( str_option-w_height*2>=0 ){
        str_option-=w_height; break;   }
      else
        str_option=w_ligter=0;
      }
    break;
 case PGDN: if(str_end>0){
       if( str_option==str_end-1 ){need_draw=0; break; }
                     must_redraw=1;
       str_old_option=str_option;
       w_old_ligter=w_ligter;
       if( str_option+w_height<str_end )
         str_option+=w_height;
       else{
         str_option=str_end-1;
         if( str_end<w_height )
    w_ligter=str_end-1;
         else
    w_ligter=w_height-1;
         }
       }
     break;
 case ESC:  return(NOSELECT);
 case ENTER:return(str_option);
 default:   need_draw=0;
     continue;
 }  /* end switch */
      }   /* if kbhit() end */
    }   /* end for */
}   /* end function */

int WinReadTxt(struct CReadTxt r)
{  int x, y, l, t;
  struct CDialog bm;
  if( (r.txtbottom-r.txttop)%16!=0 || (r.txtright-r.txtleft)%16!=0 ){
     SystemError.str1="函数ReadTxtFile出错,边界未对齐";
     SystemError.str2="显示区域的长&宽皆应为16的倍数";
     MessageBox( &SystemError );
     return(ERROR);
     }
  bm.title=r.txtfilename;
  bm.left=r.left; bm.top=r.top;
  bm.right=r.right;    bm.bottom=r.bottom;
  wl=r.txtleft;  wt=r.txttop;  wr=r.txtright;  wb=r.txtbottom;
  bm.close=1;      bm.move=1;
  bm.draw=null; bm.react=ActTxtWinButton;
  if( (TxtFileHandle=fopen(r.txtfilename,"rb"))==NULL)  return(ERROR);
  if( InitDialog( &bm )==ERROR )    return(ERROR);
/* sub init readtxt window */
   Button(bm.right-20,bm.top+20,NULL,"U",BUTTON_UP);
   Button(bm.right-20,bm.bottom-20,NULL,"d",BUTTON_UP);
   WinMake(bm.right-19,bm.top+22+16,bm.right-20+15,/
/*上翻页*/    bm.top+20+(bm.bottom-bm.top-20)/2,LIGHTGRAY,BUTTON_FRAME,BUTTON_UP);
   WinMake(bm.right-19,bm.top+22+(bm.bottom-bm.top-20)/2,bm.right-20+15,/
/*下翻页*/         bm.bottom-22,LIGHTGRAY,BUTTON_FRAME,BUTTON_UP);
   mouse_off();
   ReadTxtFile( bm.left+wl,bm.top+22+wt,bm.left+wr,bm.top+22+wb,INITTXTWIN);
   mouse_on();
/* end init */
   RunDialog( &bm );
   fclose(TxtFileHandle);
   return(OK);
}

int ActTxtWinButton(int mx,int my,struct CDialog bm)
{
 int key;
 if( InBar(mx,my,bm.right-19,bm.top+21+16,bm.right-20+16,/
       /* PGUP */        bm.top+20+(bm.bottom-bm.top-20)/2) )
   key=PGUP;
 if( InBar(mx,my,bm.right-19,bm.top+22+(bm.bottom-bm.top-20)/2,/
       /* PGDN */  bm.right-20+16,bm.bottom-22) )
   key=PGDN;
 if( InBar(mx,my,bm.right-20,bm.top+20,bm.right-20+16,bm.top+20+16) )
   key=UP;
 if( InBar(mx,my,bm.right-20,bm.bottom-4-16,bm.right-20+16,bm.bottom-4) )
   key=DOWN;
 if( key==UP || key==DOWN || key==PGUP || key==PGDN ){
    mouse_off();
    while( !LBUTTON_UP )
      ReadTxtFile(bm.left+wl,bm.top+22+wt,bm.left+wr,bm.top+22+wb,key);
    reset_event_status();
    mouse_on();
    return(DIALOG_NOT_CLOSE);
    }
 if( Kbhit() ){
   key=GetKey();    ClearKeyBuffer();
   if( key==ESC ) return(DIALOG_CLOSE);
   if( key==UP||key==DOWN||key==PGUP||key==PGDN ){
     mouse_off();
     ReadTxtFile(bm.left+wl,bm.top+22+wt,bm.left+wr,bm.top+22+wb,key);
     mouse_on();
     return(OK);
     } /* if have txtwinkey is pressed end */
   else return(OK);
   }
}

int ReadTxtFile(int left,int top,int right,int bottom,int key)
/* 显示区的长度与宽度必须同时为16的倍数 */
{
  char tmp[3];
  char *linenumerr="所定义文本行数小于显示的文本行数";
  static unsigned long count1,count2;
  static int x,y,maxline,linenum=0;
  static long fileoffset;
  static unsigned char endflag,eoln;
  unsigned char ch1,ch2;
  int backactionbutton=0; /* 当显示完毕后,返回响应函数的标志 */
  if( linenum>=MAXLINENUM ){
    SystemError.str1=linenumerr;
    MessageBox( &SystemError );
    return(ERROR);
    }
  setfillstyle(SOLID_FILL,TXT_WIN_BACKGROUND);
  if( key!=INITTXTWIN ) goto JMP_HERE;
  bar(left,top,right,bottom);
  for(count1=1;count1<MAXLINENUM;count1++) lineaddr[count1]=-1L;
  maxline=(bottom-top)/16;
  x=left; y=top;
  linenum=0;
  lineaddr[0]=fileoffset=0L;
  endflag=0;
  count1=count2=0;
  while(1){
    endflag=0;
    while(!endflag){
      eoln=0;
      while(!eoln){
 if(count2==count1){
   if(count1!=0)  fileoffset+=XMS_BUF-10;
   if((count2<XMS_BUF-10) && (count2!=0)){
     endflag=1;
     break;
     }
   if( (count1=read(fileno(TxtFileHandle),xms_2_basemem_buffer,(int)XMS_BUF-10))==-1) /* 有可能读失败 */
     return( ERROR );
   count1--;
   if(count1<XMS_BUF-10){
     for(count2=count1;count2<XMS_BUF-10;++count2)  xms_2_basemem_buffer[count2]=0;
     }
   count2=0;
   }
      ch1=xms_2_basemem_buffer[count2++];
      if( ch1&0x80 ){
  tmp[0]=ch1; tmp[1]=(unsigned char)xms_2_basemem_buffer[count2++];tmp[2]='/0';
  setviewport(left,top,right,bottom,1);
  OutText(x-left,y-top,TXT_WIN_TEXT,tmp);
  setviewport(0,0,639,479,1);
  if( x+16>right ) count2-=2;
  x+=16;
       }
      else{
  switch(ch1){
    case '/r':
  break;
    case '/n':
  y+=16;
  x=left;
  eoln=1;
  lineaddr[++linenum]=fileoffset+count2;
  break;
    case '/t':
  x+=64;
  break;
    default:
  tmp[0]=ch1;  tmp[1]='/0';
  setviewport(left,top,right,bottom,1);
  OutText(x-left,y-top,TXT_WIN_TEXT,tmp);
  setviewport(0,0,639,479,1);
  x+=8;
  break;
  }
    }
    if(x>=right){
      lineaddr[++linenum]=fileoffset+count2;
      y+=16;
      x=left;
      eoln=1;
      }
    }
  if( linenum>=MAXLINENUM ){
    SystemError.str1=linenumerr;
    MessageBox( &SystemError );
    return(ERROR);
    }
  if( (y>=bottom) || (count1<XMS_BUF-10) && (count1==count2) ){
JMP_HERE:
    if( key==INITTXTWIN ) return(OK);
    if( backactionbutton ) return(OK);
           x=left; y=top;
           bar(left,top,right,bottom);
    backactionbutton=1;
    switch( key ){
      case ESC:
  return(DIALOG_CLOSE);
      case PGUP:
  linenum-=maxline*2;
  if(linenum<0) linenum=0;
  fileoffset=lineaddr[linenum];
  fseek(TxtFileHandle,fileoffset,SEEK_SET);
  count1=count2=0;
  break;
      case PGDN:
  if(linenum<0) linenum=0;
  fileoffset=lineaddr[linenum];
  fseek(TxtFileHandle,fileoffset,SEEK_SET);
  count1=count2=0;
  break;
      case UP:
  linenum-=maxline+1;
  if(linenum<0) linenum=0;
  fileoffset=lineaddr[linenum];
  fseek(TxtFileHandle,fileoffset,SEEK_SET);
  count1=count2=0;
  break;
      case DOWN:
  linenum-=maxline-1;
  if(linenum<0) linenum=0;
  fileoffset=lineaddr[linenum];
  fseek(TxtFileHandle,fileoffset,SEEK_SET);
  count1=count2=0;
  break;
      } /* switch end */
    }
   }  /* while end */
    }  /* while end */
}  /* function end */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值