⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tw2.cpp

📁 本软件是简单的文本编辑器
💻 CPP
字号:
/********************************************
				Tw2.cpp文件
定义了本软件中最重要的文本编辑窗类TextWindows
通过该类,用户可以完成插入、删除和块操作等编辑
功能。
*********************************************/

#define mINITBUF 20
#define	mADDBUF 15
#define mREFRESHALL 0
#define mREFRESHLINE 1
#define mWINCOLOR    (BLUE<<12)|(WHITE<<8)
#define mWINCOLOR2   (BLUE<<12)|(LIGHTGRAY<<8)
#define mTEXTCOLOR   (BLUE<<12)|(YELLOW<<8)
#define mBLOCKCOLOR  (LIGHTGRAY<<12)|(BLUE<<8)
#define mF1		0xff3b
#define mF2     0xff3c
#define mF3     0xff3d
#define mF4     0xff3e
#define mF5     0xff3f
#define mF6     0xff40
#define mF7     0xff41
#define mF8     0xff42
#define mF9     0xff43
#define mF10    0xff44

typedef struct TextLine
{
char *TheLine;				//该行字符串指针
int iLinelen;				//字符数
int iBuflen;				//该行字符串存储空间总数
TextLine *NextLine;			//下一行指针
}Textline;

class TextWindows:public Item
{
  private:
  TextLine *Head;					//行结构体指针
    char CurrentFile[256];			//文件名
    char cState;  	// wwwwbn0c B  n:New,b:block defining,c:Change,wwww:windows number
    		   		//窗口状态字,高四位表示窗口号,第3位为1时表示块定义状态,
					//第2位为1时表示是新文件,第1位未使用,
					//第0位为1时表示文件被修改
int iAbsPrex,iAbsPrey;						//前次光标在整个文件中的(逻辑)位置
    int iAbsCurx,iAbsCury;					//当前光标在整个文件中的(逻辑)位置
    int iBlockTop,iBlockLeft,iBlockBottom,iBlockRight;	//块位置
    int iStartRow,iStartColm;				//文件在窗口中显示的开始行、开始列
    int iTotalLine;							//文件总行数
    void BlockCopy();						//块复制函数
    void BlockDef();						//块定义函数
    void BlockDel();						//块删除函数
    void BlockInsert();						//块插入函数
    void BlockSelAll();						//全选
    void CurMov(int cInChar);				//光标移动函数
    void DrawWin(int iMode);				//窗口边框绘制函数
    void GetCurPose(Textline* &CurRow,char* &CurColm);	//得到光标所在处的行、列指针
    void InsertChar(int cInChar);				//插入字符函数
    void MouseButtonDown(int iScrPose,char cButton);	//鼠标按键按下响应
    void MouseClick(int iScrPose,char cButton);		//鼠标点击响应
    void MouseMove(int iScrPose,char cButton);		//鼠标移动响应
    void TextNew();							//新建窗口函数
    int TextLoad();							//文件调入函数
    int TextSave(char cSaveMode=0);			//文件保存函数
    void TextSearch(int iMode);				//字符串查找函数
    void TextRefresh(int iMode=mREFRESHALL);	//窗口内容刷新函数
  public:
    char cTop,cLeft,cHeight,cWidth;			//窗口位置
    TextWindows(char cWinNum);				//窗口初始化
    ~TextWindows();
    void ComMsg(Msg TheMsg);				//消息接口函数
};

//文本编辑框构造函数
TextWindows::TextWindows(char cWinNum)
{
 Head=NULL;					//清空行链表
 *CurrentFile='\0';			//清空文件名
 iBlockTop=1;				//清除块
 iBlockLeft=1;
 iBlockBottom=0;
 iBlockRight=0;
 cState=cWinNum<<4;			//设定窗口号
 cTop=2;cLeft=1;
 cHeight=25-cTop+1;
 cWidth=80-cLeft+1;
 TextNew();					//新建窗口
}

//窗口析构函数
TextWindows::~TextWindows()
{
 TextNew();					//清除文本框内容
 free(Head->TheLine);		//释放第一行结点所占用的空间
 free(Head);
 textattr(BLACK<<4|LIGHTGRAY);
}

//块定义函数
void TextWindows::BlockDef()
{
  //根据光标的位置和块位置之间的关系判断块的新位置

  //如果光标的前次位置在块的头
  if(iAbsPrex==iBlockLeft&&iAbsPrey==iBlockTop)
  {
    if(iAbsCury<iBlockBottom||
       iAbsCury==iBlockBottom&&
       iAbsCurx<=iBlockRight)	//如果光标当前的位置在块尾的前面
    {
      iBlockLeft=iAbsCurx;		//那么改变块头的位置
      iBlockTop=iAbsCury;
    }
    else
    {
      iBlockRight=iAbsCurx-1;	//否则改变块尾的位置
      iBlockBottom=iAbsCury;
    }
  }

  //如果光标的前次位置在块的尾
  else if(iAbsPrex==iBlockRight+1&&iAbsPrey==iBlockBottom)
  {

    if(iAbsCury>iBlockTop||
       iAbsCury==iBlockTop&&
       iAbsCurx>=iBlockLeft)	//如果光标当前的位置在块头的后面
    {
      iBlockRight=iAbsCurx-1;	//那么改变块尾的位置
      iBlockBottom=iAbsCury;
    }
    else
    {
      iBlockLeft=iAbsCurx;		//否则改变块头的位置
      iBlockTop=iAbsCury;
    }
  }

  //其他情况重新定义块
  else
  {	//根据光标前次的位置和当前的位置,设定块的位置。
    if(iAbsPrey<iAbsCury)
    {
      iBlockLeft=iAbsPrex;
      iBlockTop=iAbsPrey;
      iBlockBottom=iAbsCury;
      iBlockRight=iAbsCurx-1;
    }
    else if(iAbsPrey>iAbsCury)
    {
      iBlockLeft=iAbsCurx;
      iBlockTop=iAbsCury;
      iBlockBottom=iAbsPrey;
      iBlockRight=iAbsPrex-1;
    }
    else
    {
      iBlockLeft=iAbsPrex<iAbsCurx?iAbsPrex:iAbsCurx;
      iBlockRight=iAbsPrex<iAbsCurx?iAbsCurx-1:iAbsPrex-1;
      iBlockTop=iBlockBottom=iAbsPrey;
    }
  }
}

//块复制函数
void TextWindows::BlockCopy()
{
  TextLine *CurLine;
  int iCountLine,iCountColm;
  char *cTmp;

  //打开剪切板
  ClipBoard.ClpOpen();

  //找到块头对应的行
  for(iCountLine=1,CurLine=Head;
      iCountLine!=iBlockTop&&CurLine;
      iCountLine++,CurLine=CurLine->NextLine);
  
  //将块头行和块尾行之间的字符存储到剪切板
  for(;iCountLine<=iBlockBottom&&CurLine;
      iCountLine++,CurLine=CurLine->NextLine)
    {
      cTmp=CurLine->TheLine;
      for(iCountColm=0;cTmp[iCountColm];iCountColm++)
      {
	if(iCountLine==iBlockTop&&
	   iCountColm+1<iBlockLeft||
	   iCountLine==iBlockBottom&&
	   iCountColm+1>iBlockRight)
	   continue;
	else	//如果字符的位置在块内,那么将字符复制到剪切板
	   ClipBoard.ClpWrite(cTmp[iCountColm]);
      }
    }
  ClipBoard.ClpClose();
}

//块删除函数
void TextWindows::BlockDel()
{
   TextLine *TopLine,*ButtonLine,*TmpLine;
   char *cLeft,*cRight;

   //如果块位置不合适,函数返回
   if(iBlockTop>iBlockBottom) return;
   if(iBlockTop==iBlockBottom&&iBlockRight<iBlockLeft) return;
   
   //寻找到块尾指针
   iAbsPrex=iAbsCurx;iAbsPrey=iAbsCury;
   iAbsCurx=iBlockRight;iAbsCury=iBlockBottom;
   GetCurPose(ButtonLine,cRight);
   
   //寻找到块头指针
   iAbsCurx=iBlockLeft;iAbsCury=iBlockTop;
   GetCurPose(TopLine,cLeft);
   
   //截断块头行
   *cLeft='\0';

   //如果块头行的存储空间不够用,那么就开辟新空间
   if(TopLine->iBuflen<=strlen(TopLine->TheLine)+strlen(cRight))
   {
     TopLine->TheLine=(char*)realloc(TopLine->TheLine,
				   TopLine->iBuflen=strlen(TopLine->TheLine)+strlen(cRight)+mADDBUF);
   }

   strcat(TopLine->TheLine,cRight+1);		//将块尾行的剩余字符追加到块头行
   TopLine->iLinelen=strlen(TopLine->TheLine);
   if(TopLine->TheLine[TopLine->iLinelen-1]!='\n')	//加行结尾符
     TopLine->TheLine[TopLine->iLinelen++]='\n';
   TopLine->TheLine[TopLine->iLinelen]='\0';
   TopLine->iLinelen++;

   //释放块头和块尾之间的行结点所占用的空间
   TmpLine=TopLine->NextLine;
   if(iBlockTop!=iBlockBottom)
   {
     //将块头行结点和块尾行结点后面结点连接起来
	 TopLine->NextLine=ButtonLine->NextLine;

	 //释放中间结点空间
     for(TopLine=TmpLine;TopLine!=ButtonLine;TopLine=TmpLine)
     {
       TmpLine=TopLine->NextLine;
       free(TopLine->TheLine);
       free(TopLine);
     }
     free(TopLine->TheLine);
     free(TopLine);
   }

   //修改有关参数
   iTotalLine-=iBlockBottom-iBlockTop;
   iBlockBottom=iBlockTop;
   iBlockRight=iBlockLeft-1;
   if(iAbsCury>=cHeight-2) iStartRow=iAbsCury-(cHeight>>1);
   else iStartRow=1;
   if(iAbsCurx>=cWidth-2) iStartColm=iAbsCurx-(cWidth>>1);
   else iStartColm=1;
   cState|=1;
   cState&=0xf7;
}

//块插入函数
void TextWindows::BlockInsert()
{
  TextLine *TopLine,*Tmp;
  char *cLeft,*cNewLine,cChar;
  int iCountLine,i;
  
  //打开剪切板
  ClipBoard.ClpOpen();
  
  //寻找插入点
  iAbsPrex=iAbsCurx;iAbsPrey=iAbsCury;
  GetCurPose(TopLine,cLeft);
  Tmp=TopLine->NextLine;
  
  if(*cLeft=='\n')		//如果插入位置在插入行的结尾以后
  {
    if(iAbsCurx+1>=TopLine->iBuflen)	//那么如果有必要,要开辟内存空间
    {
      TopLine->iBuflen=iAbsCurx+mADDBUF;
      TopLine->TheLine=(char*)realloc(TopLine->TheLine,TopLine->iBuflen);
    }
	//改变cLeft指向新的行尾
    cLeft=TopLine->TheLine;
    for(i=1;*cLeft!='\n';i++) cLeft++;
    for(;i<iAbsCurx;i++) *cLeft++=' ';	//将行尾和插入点之间添入空格符
    *(cLeft)='\n';*(cLeft+1)='\0';
  }

  //保存插入点后面的字符串
  cNewLine=(char*)malloc(strlen(cLeft)+1);
  strcpy(cNewLine,cLeft);
  iBlockTop=iAbsCury;
  iBlockLeft=iAbsCurx;
  for(i=cLeft-TopLine->TheLine,iCountLine=0;
      (cChar=ClipBoard.ClpRead())!='\0';i++)	//循环从剪切板中读出字符
    {
      if(i+2>=TopLine->iBuflen)			//如果插入行空间不够
      {
	TopLine->iBuflen+=mADDBUF;			//开辟新空间
	TopLine->TheLine=(char*)realloc(TopLine->TheLine,TopLine->iBuflen);
      }
      TopLine->TheLine[i]=cChar;		//插入字符
      if(cChar=='\n')					//如果遇到回车符,建立新的行结点
      {
	TopLine->TheLine[++i]='\0';			//结束当前行
	TopLine->iLinelen=i+1;
	TopLine->NextLine=(TextLine*)malloc(sizeof(TextLine));	//建立新结点
	TopLine->NextLine->iBuflen=mINITBUF;
	TopLine->NextLine->TheLine=(char*)malloc(mINITBUF);	//为一行字符串开辟空间
	TopLine=TopLine->NextLine;	
	iCountLine++;
	i=-1;
      }
    }
  TopLine->TheLine[i]='\0';

  //将插入点后面的字符串追加到最后新建行的末尾
  if(strlen(TopLine->TheLine)+strlen(cNewLine)+1>=TopLine->iBuflen)
    {//如果空间不够,开辟新空间
      TopLine->iBuflen+=mADDBUF;
      TopLine->TheLine=(char*)realloc(TopLine->TheLine,TopLine->iBuflen);
    }
  strcat(TopLine->TheLine,cNewLine);
  free(cNewLine);
  TopLine->iLinelen=strlen(TopLine->TheLine)+1;
  TopLine->NextLine=Tmp;	//将插入点后面的行链入

  //窗口参数做相应调整
  iTotalLine+=iCountLine;
  iAbsCury=iBlockBottom=iBlockTop+iCountLine;
  iAbsCurx=(iBlockRight=i)+1;
  if(iAbsCury>=cHeight-2) iStartRow=iAbsCury-(cHeight>>1);
  else iStartRow=1;
  if(iAbsCurx>=cWidth-2) iStartColm=iAbsCurx-(cWidth>>1);
  else iStartColm=1;
  cState|=1;
}

//全选函数
void TextWindows::BlockSelAll()
{
  TextLine *CurLine;
  char *CurColm;
  //改变状态字
  cState|=8;
  //改变光标位置
  iAbsPrex=iAbsCurx;
  iAbsPrey=iAbsCury;
  iAbsCury=iTotalLine;
  //定义块
  GetCurPose(CurLine,CurColm);
  iAbsCurx=CurLine->iLinelen-1;
  iBlockTop=iBlockLeft=1;
  iBlockBottom=iAbsCury;
  iBlockRight=iAbsCurx-1;
}

//消息接口函数
void TextWindows::ComMsg(Msg TheMsg)
{
 switch(TheMsg.iOpera)
 {
   case mITEMREFRESH:					//刷新
     TextRefresh(0);
     break;
   case mWINNEW:						//新建文件
     TextNew();
     TextRefresh(mREFRESHALL);
     break;
   case mWINLOAD:						//调入文件
     TextLoad();
     TextRefresh(mREFRESHALL);
     break;
   case mWINSAVE:						//保存文件
     TextSave();
     break;
   case mWINSAVEAS:						//文件另存为
     TextSave(1);
	 break;
   case mKEY:							//键盘有键入
     InsertChar(TheMsg.iAgu2);
   case mCURMOV:						//光标移动
     CurMov(TheMsg.iAgu2);
     break;
   case mWINBLOCKDEF:					//块定义
     CurMov(TheMsg.iAgu2);
     BlockDef();
     TextRefresh();
     break;
   case mWINCOPY:						//块复制
     BlockCopy();
     break;
   case mWINCUT:						//块剪切
     BlockCopy();
     BlockDel();
     TextRefresh();
     break;
   case mWINPASTE:						//块粘贴
     BlockInsert();
     TextRefresh();
     break;
   case mWINBLOCKDEL:					//块删除
     BlockDel();
     TextRefresh();
     break;
   case mWINSEARCHFOR:					//查找新字符串
     TextSearch(mWINSEARCHFOR);
     break;
   case mWINSEARCHNEXT:					//查找下一个匹配字符串
     TextSearch(mWINSEARCHNEXT);
     break;
   case mWINGETFOCUS:					//文本框得到焦点
     DrawWin(1);
     _setcursortype(_NORMALCURSOR);
     break;
   case mWINLOSFOCUS:					//文本框得到焦点
     DrawWin(0);
     _setcursortype(_NOCURSOR);
     break;
   case mWINSELALL:						//全选
     BlockSelAll();
     TextRefresh();
     break;
   case mMOUSECLICK:					//鼠标点击
     MouseClick(TheMsg.iAgu1,TheMsg.iAgu2);
     cState&=0xf7;
     break;
   case mMOUSEBUTTONDOWN:				//鼠标左键按下
     MouseButtonDown(TheMsg.iAgu1,TheMsg.iAgu2);
     break;
   case mMOUSEMOVE:						//鼠标移动
     MouseMove(TheMsg.iAgu1,TheMsg.iAgu2);
 }
}

//光标移动
void TextWindows::CurMov(int cInChar)
{
 char cKey=cInChar>>8,cExKey=cInChar&0xff;
 int iNeedRefresh=0;
 TextLine *CurLine;
 char *CurColm;
 GetCurPose(CurLine,CurColm);
 if(!cKey)			//如果是非扩展字符键入
   iNeedRefresh=1;
 else
 {
   iAbsPrex=iAbsCurx;
   iAbsPrey=iAbsCury;
   switch(cExKey)	//如果是扩展字符键入,那么分析键码
   {
     case 72:iAbsCury-=1;break; //分别是上下左右键键入
     case 75:iAbsCurx-=1;break;
     case 77:iAbsCurx+=1;break;
     case 80:iAbsCury+=1;break;
     case 73:			//PageUp键键入
       iAbsCury-=cHeight-3;
       iStartRow-=cHeight-3;
       iNeedRefresh=1;
       break;
     case 81:			//PageDown键键入
       iAbsCury+=cHeight-3;
       iStartRow+=cHeight-3;
       iNeedRefresh=1;
       break;
     case 71:iAbsCurx=1;break;	//Home键键入
     case 79:					//End键键入
       iAbsCurx=CurLine->iLinelen-1;
       break;
     case 83:			//Del键键入,将光标移动到当前位置的后面一个位置
       if(*CurColm=='\n')	//如果是行尾,那么将光标转移到下一行行首
       {iAbsCury++;iAbsCurx=1;}
       else iAbsCurx++;
       InsertChar(8);		//调用字符插入函数,插入字符尾退格键
       iNeedRefresh=1;
   };
 }

 //修改窗口参数
 if(iAbsCury>iTotalLine) iAbsCury=iTotalLine;
 if(iAbsCurx<iStartColm||
    iAbsCurx>iStartColm+cWidth-3||
    iAbsCury<iStartRow||
    iAbsCury>iStartRow+cHeight-3)
   iNeedRefresh=1;
 else
   gotoxy(iAbsCurx-iStartColm+cLeft+1,
	  iAbsCury-iStartRow+cTop+1);
 if(iNeedRefresh) TextRefresh(mREFRESHALL);
}

//绘制文本编辑窗边框函数
void TextWindows::DrawWin(int iMode)
{
  int x,y;
  int iShowBuf[78];
  
  //根据不同的模式选择不同的屏幕显示模式
  iShowBuf[0]=iMode?0xff&'

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -