/* * QT AGI Studio :: Copyright (C) 2000 Helen Zommer * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "logedit.h" #include "game.h" #include "menu.h" #include "agicommands.h" #include #include #include #ifndef _WIN32 #include #include #endif #include #include #include #include #include #include #include //Added by qt3to4: #include #include #include #include #include #include #include #include #include #include TStringList InputLines; //temporary buffer for reading the text from editor //and sending to compilation //*********************************************** // Syntax highlight static QString operators ="!-+=<>/*&|^%", wordchars = "0123456789abcdefghijlkmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ._#"; static QColor normal_color = QColor("black"), comment_color = QColor("#808080"), string_color = QColor("red"), number_color = QColor("darkCyan"), command_color = QColor("darkBlue"), test_color = QColor("brown"), operator_color = QColor("blue"); class LogicSyntaxHL : public Q3SyntaxHighlighter { public: LogicSyntaxHL( Q3TextEdit* te ) : Q3SyntaxHighlighter( te ) {} void highlightWord( const QString& line, int start, int len ) { QColor* col = 0; QString word( line.mid(start, len)); // Number? if ( word.find(QRegExp("[^0-9]")) < 0 ) col = &number_color; else { // AGI command? for ( CommandStruct* cmd = AGICommand; cmd < AGICommand + (sizeof(AGICommand)/sizeof(CommandStruct)); ++cmd ) { if ( word == cmd->Name ) { col = &command_color; break; } } // AGI test command? for ( CommandStruct* cmd = TestCommand; cmd < TestCommand + (sizeof(TestCommand)/sizeof(CommandStruct)); ++cmd ) { if ( word == cmd->Name ) col = &test_color; } // Control structure if ( word[0]=='#' || word == "if" || word == "else" || word == "goto" ) col = &operator_color; } if ( col ) setFormat( start, len, *col); } int highlightParagraph ( const QString & text, int endStateOfLastPara ) { setFormat( 0, text.length(), normal_color); QString txt = text; int comment_depth = endStateOfLastPara; bool in_quotes = (comment_depth==-1); if ( comment_depth < 0 ) comment_depth = 0; int curchar = 0, lastchar = 0; while( !txt.isEmpty()) { // Get next line & shorten int eol = txt.find( '\n' ); if ( eol < 0 ) eol = txt.length()-1; QString line = txt.mid(0,eol); txt = txt.mid(eol+1); bool in_word = false; // Process the line int i; for ( i=0; i<(int)line.length(); ++i ) { // Single words if ( in_word && wordchars.find(line[i]) < 0 ) { highlightWord( line, lastchar, curchar+i-lastchar ); in_word = false; } // Comments if ( !in_quotes ) { if (comment_depth==0 && line.mid(i,1) == "[") { setFormat( (curchar+i), line.length()-i+1, comment_color); break; } // More than two chars left? if ( i<(int)line.length()-1 ) { if (comment_depth==0 && (line.mid(i,2) == "//" )) { setFormat( (curchar+i), line.length()-i+1, comment_color); break; } else if ( line.mid(i,2) == "/*") { if ( comment_depth == 0 ) lastchar = (curchar+i); ++comment_depth; ++i; continue; } else if (comment_depth>0 && line.mid(i,2) == "*/" ) { --comment_depth; if ( comment_depth == 0 ) { setFormat( lastchar, (curchar+i)-lastchar+2, comment_color); lastchar = (curchar+i+2); } ++i; continue; } } } // Quotes if ( comment_depth == 0 ) { if(line[i]=='\"' && (i==0 || line[i-1] != '\\')) { if ( in_quotes ) setFormat( lastchar, (curchar+i)-lastchar+1, string_color); lastchar = curchar+i; in_quotes = !in_quotes; } if ( !in_quotes ) { if( !in_word && wordchars.find(line[i]) >= 0 && (i==0 || wordchars.find(line[i-1]) < 0 )) { in_word = true; lastchar = curchar+i; } else if ( operators.find(line[i]) >= 0 ) setFormat((curchar+i), 1, operator_color); } } } // End of line, format word if still open if ( in_word ) highlightWord( line, lastchar, line.length()-lastchar ); curchar += i; if ( in_quotes ) setFormat( lastchar, curchar-lastchar+1, string_color); } // End of paragraph, format comment block if still open if ( comment_depth > 0 ) setFormat( lastchar, curchar-lastchar+1, comment_color); return (in_quotes ? -1 : comment_depth); } }; //*********************************************** LogEdit::LogEdit( QWidget *parent, const char *name, int win_num, ResourcesWin *res, bool readonly) : QWidget( parent, name, Qt::WDestructiveClose ) , findedit(NULL) , roomgen(NULL) { setCaption("Logic editor"); logic = new Logic(); winnum = win_num; //my window number resources_win = res; //resources window which called me editor = new Q3MultiLineEdit(this); QFont font("Monospace"); font.setPointSize(readonly?8:9); font.setStyleHint( QFont::TypeWriter ); editor->setFont( font ); editor->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding )); editor->setWordWrap( Q3TextEdit::NoWrap ); syntax_hl = new LogicSyntaxHL( editor ); if ( readonly ) { editor->setReadOnly( readonly ); } else { editor->setMinimumSize(512,600); setMinimumSize(450,400); } setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding )); Q3BoxLayout *all = new Q3VBoxLayout(this,10); all->addWidget(editor); if ( !readonly ) { Q3PopupMenu *file = new Q3PopupMenu( this ); Q_CHECK_PTR( file ); file->insertItem( "Read from file", this, SLOT(read_logic()) ); file->insertItem( "Save", this, SLOT(save_logic()), Qt::CTRL + Qt::Key_S ); file->insertItem( "Save as", this, SLOT(save_as()) ); file->insertItem( "Compile", this, SLOT(compile_logic()) ,Qt::Key_F9 ); file->insertItem( "Compile all", this, SLOT(compile_all_logic()) ); file->insertItem( "Compile all and run", this, SLOT(compile_and_run()) ,Qt::Key_F10 ); file->insertItem( "Change logic number", this, SLOT(change_logic_number()) ); file->insertSeparator(); file->insertItem( "Delete", this, SLOT(delete_logic()) ); file->insertItem( "New room", this, SLOT(new_room()) ); file->insertSeparator(); file->insertItem( "Close", this, SLOT(close()) ); Q3PopupMenu *edit = new Q3PopupMenu( this ); Q_CHECK_PTR( edit ); edit->insertItem( "Cut", editor, SLOT(cut()) , Qt::CTRL + Qt::Key_X ); edit->insertItem( "Copy", editor, SLOT(copy()) , Qt::CTRL + Qt::Key_C ); edit->insertItem( "Paste", editor, SLOT(paste()) , Qt::CTRL + Qt::Key_V); edit->insertSeparator(); edit->insertItem( "Clear all", this, SLOT(clear_all()) ); edit->insertSeparator(); edit->insertItem( "Find", this, SLOT(find_cb()) ,Qt::CTRL + Qt::Key_F); edit->insertItem( "Find again", this, SLOT(find_again()) ,Qt::Key_F3); edit->insertSeparator(); edit->insertItem( "Go to line", this, SLOT(goto_cb()) ,Qt::ALT + Qt::Key_G); Q3PopupMenu *help = new Q3PopupMenu( this ); Q_CHECK_PTR( help ); help->insertItem( "Context help", this, SLOT(context_help()), Qt::Key_F1); help->insertItem( "All commands", this, SLOT(command_help())); QMenuBar *menu = new QMenuBar(this); Q_CHECK_PTR( menu ); menu->insertItem( "File", file ); menu->insertItem( "Edit", edit ); menu->insertItem( "Help", help ); menu->setSeparator( QMenuBar::InWindowsStyle ); all->setMenuBar(menu); status = new QStatusBar(this); QLabel *msg = new QLabel( status, "message" ); status->addWidget( msg, 4 ); all->addWidget(status); connect( editor, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(update_line_num(int,int))); } getmaxcol(); changed=false; filename=""; hide(); } //*********************************************** void LogEdit::deinit() { if(findedit){ findedit->close(true); findedit=NULL; } if(roomgen){ roomgen->close(true); roomgen=NULL; } delete logic; logic = 0; delete syntax_hl; syntax_hl = 0; winlist[winnum].type=-1; if(window_list && window_list->isVisible())window_list->draw(); } //********************************************* void LogEdit::hideEvent( QHideEvent * ) { if(findedit){ findedit->close(true); findedit=NULL; } if(window_list && window_list->isVisible())window_list->draw(); } //********************************************* void LogEdit::showEvent( QShowEvent * ) { if(window_list && window_list->isVisible())window_list->draw(); } //*********************************************** void LogEdit::closeEvent( QCloseEvent *e ) { if(changed){ QString str = editor->text(); if(!strcmp(str.latin1(),logic->OutputText.c_str())){ //not changed deinit(); e->accept(); return; } if(LogicNum != -1){ sprintf(tmp,"Save changes to logic.%d ?",LogicNum); } else{ sprintf(tmp,"Save changes to logic ?"); } switch ( QMessageBox::warning( this, "Logic editor", tmp, "Yes", "No", "Cancel", 0, 2) ) { case 0: // yes save_logic(); deinit(); e->accept(); break; case 1: // no deinit(); e->accept(); break; default: // cancel e->ignore(); break; } } else{ deinit(); e->accept(); } } //*********************************************** int LogEdit::open() { getmaxcol(); LogicNum = -1; show(); changed=true; return 0; } //*********************************************** int LogEdit::open(char *filenam) { getmaxcol(); FILE *fptr = fopen(filenam,"rb"); if(fptr!=NULL){ filename = string(filenam); editor->clear(); char *ptr; QString filecont; while(fgets(tmp,MAX_TMP,fptr)!=NULL){ if((ptr=(char*)strchr(tmp,0x0a))) *ptr=0; if((ptr=(char*)strchr(tmp,0x0d))) *ptr=0; filecont += QString(tmp) + "\n"; } editor->setText( filecont ); fclose(fptr); logic->OutputText=editor->text().latin1(); if((ptr=(char*)strrchr(filename.c_str(),'/')))ptr++; else ptr=(char *)filename.c_str(); if(LogicNum!=-1) sprintf(tmp,"logic.%d (file %s)",LogicNum,ptr); else sprintf(tmp,"logic (file %s)",ptr); setCaption(tmp); show(); changed=true; return 0; } else{ menu->errmes("Can't open file %s !",filenam); //QMessageBox::critical( this, "Agistudio", // QString( "Can't open file '" ) + filenam + "'"); return 1; } } //*********************************************** int LogEdit::open(int ResNum) { int err=0; QString str; FILE *fptr; getmaxcol(); logic->maxcol=maxcol; //look for the source file first sprintf(tmp,"%s/logic.%03d",game->srcdir.c_str(),ResNum); fptr = fopen(tmp,"rb"); if(fptr==NULL){ sprintf(tmp,"%s/logic.%d",game->srcdir.c_str(),ResNum); fptr = fopen(tmp,"rb"); } if(fptr==NULL){ sprintf(tmp,"%s/logic%d.txt",game->srcdir.c_str(),ResNum); fptr = fopen(tmp,"rb"); } if(fptr!=NULL){ LogicNum = ResNum; err=open(tmp); } else{ //source file not found - reading from the game err=logic->decode(ResNum); if(!err)editor->setText(logic->OutputText.c_str()); else { sprintf(tmp,"logic.%d",ResNum); menu->errmes(tmp,"Errors:\n%s",logic->ErrorList.c_str()); } str.sprintf("logic.%d",ResNum); setCaption(str); LogicNum = ResNum; show(); changed=true; } return err; } //*********************************************** void LogEdit::save(char *filename) { QString str; byte *s; FILE *fptr; if((fptr=fopen(filename,"wb"))==NULL){ menu->errmes("Can't open file %s !\n",filename); return; } for(int i=0;inumLines();i++){ str = editor->textLine(i); if(!str.isNull()){ s = (byte *)str.latin1(); fprintf(fptr,"%s\n",s); } } fclose(fptr); changed=false; } //*********************************************** void LogEdit::save_logic() { if(LogicNum==-1){ save_as(); } else if(filename != ""){ save((char *)filename.c_str()); char *ptr; if((ptr=(char*)strrchr(filename.c_str(),'/')))ptr++; else ptr=(char *)filename.c_str(); sprintf(tmp,"File %s",ptr); setCaption(tmp); } else{ sprintf(tmp,"%s/logic.%03d",game->srcdir.c_str(),LogicNum); save(tmp); sprintf(tmp,"Logic %d (file)",LogicNum); setCaption(tmp); } } //*********************************************** void LogEdit::save_as() { Q3FileDialog *f = new Q3FileDialog(0,"Save",true); const char *filters[] = {"logic*.*","All files (*)",NULL}; f->setFilters(filters); f->setCaption("Save"); f->setMode(Q3FileDialog::AnyFile); f->setDir(game->srcdir.c_str()); if ( f->exec() == QDialog::Accepted ) { if ( !f->selectedFile().isEmpty() ) save((char *)f->selectedFile().latin1()); } } //*********************************************** void LogEdit::read_logic() { Q3FileDialog *f = new Q3FileDialog(0,"Read",true); const char *filters[] = {"logic*.*","All files (*)",NULL}; f->setFilters(filters); f->setCaption("Read"); f->setMode(Q3FileDialog::ExistingFile); f->setDir(game->srcdir.c_str()); if ( f->exec() == QDialog::Accepted ) { if ( !f->selectedFile().isEmpty() ) open((char *)f->selectedFile().latin1()); } } //*********************************************** int LogEdit::compile_all_logic() { int ret,err=0; for(int i=0;icompile_logic(); if(ret)err=1; } } return err; } //*********************************************** int LogEdit::compile_logic() { QString str; byte *s; int err,i; string filename; char name[128]; char tmp1[16],*ptr,*ptr1; InputLines.lfree(); for(i=0;inumLines();i++){ str = editor->textLine(i); if(!str.isNull() && str.length()>0){ s = (byte *)str.latin1(); if(s[0]<0x80) //i'm getting \221\005 at the last line... InputLines.add((char *)str.latin1()); } else{ InputLines.add(""); } } for(i=0;ifilename != ""){ winlist[i].w.t->save(); winlist[i].w.t->status->message(""); } } } err=logic->compile(); if(!err){ status->message("Compiled OK !", 2000); if(LogicNum!=-1){ game->AddResource(LOGIC,LogicNum); save_logic(); changed=false; } } else{ if(logic->ErrorList != ""){ if(LogicNum!=-1) sprintf(tmp1,"logic.%d",LogicNum); else sprintf(tmp1,"logic"); strcpy(tmp,logic->ErrorList.c_str()); if(!strncmp(tmp,"File ",5)){ ptr=strstr(tmp,"Line "); strncpy(name,tmp+5,(int)(ptr-tmp-6)); name[(int)(ptr-tmp-6)]=0; for(i=0;ifilename; char *ptr2; if((ptr2=(char*)strrchr(filename.c_str(),'/')))ptr2++; else ptr2=(char *)filename.c_str(); if(!strcmp(ptr2,name)){ int num=atoi(ptr+5); winlist[i].w.t->editor->setCursorPosition(num,0,false); ptr1=strchr(ptr,'\n'); *ptr1=0; winlist[i].w.t->status->message(ptr); break; } } } if(i>=MAXWIN){ char fullname[256]; string tmp1=tmp; sprintf(fullname,"%s/%s",game->srcdir.c_str(),name); for(i=0;iopen(fullname); ptr=(char*)strstr(tmp1.c_str(),"Line "); int num=atoi(ptr+5); winlist[i].w.t->editor->setCursorPosition(num,0,false); ptr1=strchr(ptr,'\n'); *ptr1=0; winlist[i].w.t->status->message(ptr); break; } } } } else{ ptr=strstr(tmp,"Line "); int num=atoi(ptr+5); editor->setCursorPosition(num,0,false); ptr1=strchr(ptr,'\n'); *ptr1=0; status->message(tmp); } menu->errmes(tmp1,"Errors:\n%s",logic->ErrorList.c_str()); } } return err; } //*********************************************** void LogEdit::compile_and_run() { if(!compile_all_logic()) menu->run_game(); } //*********************************************** void LogEdit::change_logic_number() { AskNumber *changelogic = new AskNumber(0,0,"Logic number","Enter logic number: [0-255]"); if(!changelogic->exec())return; QString str = changelogic->num->text(); int num = atoi((char *)str.latin1()); if(num<0||num>255){ menu->errmes("Logic number must be between 0 and 255 !"); return ; } if(game->ResourceInfo[LOGIC][num].Exists){ sprintf(tmp,"Resource logic.%d already exists. Replace it ?",num); switch( QMessageBox::warning( this, "Logic", tmp, "Replace", "Cancel", 0, // Enter == button 0 1 ) ) { // Escape == button 1 case 0: break; case 1: return; } } LogicNum = num; compile_logic(); filename=""; save_logic(); if(resources_win){ resources_win->select_resource_type(LOGIC); resources_win->set_current(num); } open(num); } //*********************************************** void LogEdit::delete_logic() { int k; if(LogicNum==-1)return; sprintf(tmp,"Really delete logic %d ?",LogicNum); switch( QMessageBox::warning( this, "Logic", tmp, "Delete", "Cancel", 0, // Enter == button 0 1 ) ) { // Escape == button 1 case 0: game->DeleteResource(LOGIC,LogicNum); delete_file(LogicNum); if(resources_win){ k = resources_win->list->currentItem(); resources_win->select_resource_type(LOGIC); resources_win->list->setCurrentItem(k); } changed=false; close(); break; case 1: break; } } //*********************************************** void LogEdit::delete_file(int ResNum) { struct stat buf; sprintf(tmp,"%s/logic.%03d",game->srcdir.c_str(),ResNum); if(stat(tmp,&buf)==0){ unlink(tmp); } sprintf(tmp,"%s/logic.%d",game->srcdir.c_str(),ResNum); if(stat(tmp,&buf)==0){ unlink(tmp); } sprintf(tmp,"%s/logic%d.txt",game->srcdir.c_str(),ResNum); if(stat(tmp,&buf)==0){ unlink(tmp); } } //*********************************************** void LogEdit::clear_all() { switch( QMessageBox::warning( this, "Logic", "Really clear all ?", "Clear", "Cancel", 0, // Enter == button 0 1 ) ) { // Escape == button 1 case 0: editor->clear(); logic->OutputText = ""; break; case 1: break; } } //*********************************************** void LogEdit::new_room() { // FILE *fptr; switch( QMessageBox::warning( this, "Logic", "Replace the editor contents\nwith the new room template ?", "Replace", "Cancel", 0, // Enter == button 0 1 ) ) { // Escape == button 1 case 0: /* sprintf(tmp,"%s/src/newroom.txt",game->templatedir.c_str()); fptr = fopen(tmp,"rb"); if(fptr==NULL){ menu->errmes("Can't open "+string(tmp)+"!"); return; } editor->clear(); char *ptr; while(fgets(tmp,MAX_TMP,fptr)!=NULL){ if((ptr=strchr(tmp,0x0a)))*ptr=0; if((ptr=strchr(tmp,0x0d)))*ptr=0; editor->insertLine(tmp,-1); } fclose(fptr); */ if(roomgen==NULL)roomgen=new RoomGen(); if(roomgen->exec()){ editor->setText(roomgen->text.c_str()); logic->OutputText=editor->text().latin1(); changed=true; } break; case 1: break; } } //*********************************************** void LogEdit::goto_cb() { AskNumber *ask_number = new AskNumber(0,0,"Go to line", "Go to line: "); if(!ask_number->exec())return; QString str = ask_number->num->text(); int linenum = atoi((char *)str.latin1()); editor->setCursorPosition(linenum,0,false); } //*********************************************** void LogEdit::find_cb() { if(findedit==NULL)findedit = new FindEdit(NULL,NULL,editor,status); findedit->show(); findedit->find_field->setFocus(); } //*********************************************** void LogEdit::find_again() { if(findedit==NULL)find_cb(); else findedit->find_next_cb(); } //*********************************************** void LogEdit::getmaxcol() //get maximum number of columns on screen (approx.) //(for formatting the 'print' messages) { // QFontMetrics f = fontMetrics(); // maxcol = editor->width()/f.width('a'); maxcol = 50; } //*********************************************** void LogEdit::resizeEvent( QResizeEvent * ) { QString str = editor->text(); getmaxcol(); editor->setText(str); } //*********************************************** void LogEdit::context_help() { int para, index; editor->getCursorPosition( ¶, &index ); if ( para<0 || index<0 ) return; QString paratxt = editor->text( para ); int start = index, end = index; if (wordchars.find(paratxt[start]) < 0) return; // Find the bounds of the whole word while( start > 0 && wordchars.find(paratxt[start-1]) >= 0 ) --start; while( end < (int)paratxt.length() && wordchars.find(paratxt[end]) >= 0 ) ++end; QString word = paratxt.mid( start, end-start ).lower(); if (!menu->help_topic( word )) status->message("No help found for '" + word + "'", 2000); } //*********************************************** void LogEdit::command_help() { menu->help_topic("commands_by_category"); } //*********************************************** void LogEdit::update_line_num( int para, int pos ) { QString str; QTextOStream( &str ) << pos << ", " << para; status->message(str); } //******************************************************* TextEdit::TextEdit( QWidget *parent, const char *name,int win_num) : QWidget( parent, name ,Qt::WDestructiveClose ) { setCaption("Text editor"); winnum = win_num; editor = new Q3MultiLineEdit(this); editor->setMinimumSize(380,380); QFont font; font.setPointSize(10); font.setStyleHint( QFont::TypeWriter ); editor->setFont( font ); editor->setWordWrap( Q3TextEdit::NoWrap ); Q3PopupMenu *file = new Q3PopupMenu( this ); Q_CHECK_PTR( file ); file->insertItem( "New", this, SLOT(new_text())); file->insertItem( "Open", this, SLOT(open()) ); file->insertItem( "Save", this, SLOT(save()), Qt::CTRL + Qt::Key_S ); file->insertItem( "Save as", this, SLOT(save_as()) ); file->insertSeparator(); file->insertItem( "Close", this, SLOT(close()) ); Q3PopupMenu *edit = new Q3PopupMenu( this ); Q_CHECK_PTR( edit ); edit->insertItem( "Cut", editor, SLOT(cut()) , Qt::CTRL + Qt::Key_X ); edit->insertItem( "Copy", editor, SLOT(copy()) , Qt::CTRL + Qt::Key_C ); edit->insertItem( "Paste", editor, SLOT(paste()) , Qt::CTRL + Qt::Key_V); edit->insertSeparator(); edit->insertItem( "Clear all", this, SLOT(clear_all()) ); edit->insertSeparator(); edit->insertItem( "Find", this, SLOT(find_cb()) ,Qt::CTRL + Qt::Key_F); edit->insertItem( "Find again", this, SLOT(find_again()) ,Qt::Key_F3); QMenuBar *menu = new QMenuBar(this); Q_CHECK_PTR( menu ); menu->insertItem( "File", file ); menu->insertItem( "Edit", edit ); menu->setSeparator( QMenuBar::InWindowsStyle ); setMinimumSize(400,400); Q3BoxLayout *all = new Q3VBoxLayout(this,10); all->setMenuBar(menu); all->addWidget(editor); status = new QStatusBar(this); QLabel *msg = new QLabel( status, "message" ); status->addWidget( msg, 4 ); all->addWidget(status); changed=false; filename = ""; findedit=NULL; OutputText = ""; } //*********************************************** void TextEdit::deinit() { if(findedit){ findedit->close(true); findedit=NULL; } winlist[winnum].type=-1; if(window_list && window_list->isVisible())window_list->draw(); } //********************************************* void TextEdit::hideEvent( QHideEvent * ) { if(findedit){ findedit->close(true); findedit=NULL; } if(window_list && window_list->isVisible())window_list->draw(); } //********************************************* void TextEdit::showEvent( QShowEvent * ) { if(window_list && window_list->isVisible())window_list->draw(); } //*********************************************** void TextEdit::closeEvent( QCloseEvent *e ) { if(changed){ QString str = editor->text(); if(!strcmp(str.latin1(),OutputText.c_str())){ //not changed deinit(); e->accept(); return; } if(filename != "") sprintf(tmp,"Do you want to save changes to\n%s ?",filename.c_str()); else strcpy(tmp,"Do you want to save changes ?"); switch ( QMessageBox::warning( this, "Text editor", tmp, "Yes", "No", "Cancel", 0, 2) ) { case 0: // yes save(); deinit(); e->accept(); break; case 1: // no deinit(); e->accept(); break; default: // cancel e->ignore(); break; } } else{ deinit(); e->accept(); } } //*********************************************** void TextEdit::new_text() { if(filename.length()>0){ //if (changed) sprintf(tmp,"Do you want to save changes to\n%s ?",filename.c_str()); switch ( QMessageBox::warning( this, "Text editor", tmp, "Yes", "No", "Cancel", 0, 2) ) { case 0: // yes save(); //??????????????? break; case 1: // no break; default: // cancel break; } } filename=""; setCaption("New text"); editor->clear(); show(); changed=true; OutputText = ""; } //*********************************************** void TextEdit::open() { Q3FileDialog *f = new Q3FileDialog(0,"Open",true); const char *filters[] = {"All files (*)",NULL}; f->setFilters(filters); f->setCaption("Open"); f->setMode(Q3FileDialog::ExistingFile); f->setDir(game->srcdir.c_str()); if ( f->exec() == QDialog::Accepted ) { if ( !f->selectedFile().isEmpty() ){ open((char *)f->selectedFile().latin1()); show(); changed=true; } } } //*********************************************** int TextEdit::open(char *filenam) { FILE *fptr = fopen(filenam,"rb"); if(fptr!=NULL){ struct stat buf; fstat(fileno(fptr),&buf); editor->clear(); char *ptr; QString filecont; while(fgets(tmp,MAX_TMP,fptr)!=NULL){ if((ptr=strchr(tmp,0x0a)))*ptr=0; if((ptr=strchr(tmp,0x0d)))*ptr=0; filecont += QString(tmp) + "\n"; } editor->setText( filecont ); fclose(fptr); OutputText=editor->text().latin1(); filename = string(filenam); char *name = strrchr(filenam,'/'); if(name==NULL)name=filenam; else name++; QString str; str.sprintf("file %s",name); setCaption(str); show(); changed=true; return 0; } else{ menu->errmes("Can't open file %s !",filenam); return 1; } } //*********************************************** void TextEdit::save() { if(filename == ""){ save_as(); } else{ save(filename.c_str()); } } //*********************************************** void TextEdit::save_as() { Q3FileDialog *f = new Q3FileDialog(0,"Save",true); const char *filters[] = {"All files (*)",NULL}; f->setFilters(filters); f->setCaption("Save"); f->setMode(Q3FileDialog::AnyFile); f->setDir(game->srcdir.c_str()); if ( f->exec() == QDialog::Accepted ) { if ( !f->selectedFile().isEmpty() ) save((const char *)f->selectedFile().latin1()); } } //*********************************************** void TextEdit::save(const char *filename) { QString str; byte *s; FILE *fptr; if((fptr=fopen(filename,"wb"))==NULL){ menu->errmes("Can't open file %s !\n",filename); return; } for(int i=0;inumLines();i++){ str = editor->textLine(i); if(!str.isNull()){ s = (byte *)str.latin1(); fprintf(fptr,"%s\n",s); } } fclose(fptr); changed=false; char *ptr; if((ptr=(char*)strrchr(filename,'/')))ptr++; else ptr=(char *)filename; sprintf(tmp,"File %s",ptr); setCaption(tmp); } //*********************************************** void TextEdit::clear_all() { switch( QMessageBox::warning( this, "Text", "Really clear all ?", "Clear", "Cancel", 0, // Enter == button 0 1 ) ) { // Escape == button 1 case 0: editor->clear(); break; case 1: break; } } //*********************************************** void TextEdit::find_cb() { if(findedit==NULL)findedit = new FindEdit(NULL,NULL,editor,status); findedit->show(); findedit->find_field->setFocus(); } //*********************************************** void TextEdit::find_again() { if(findedit==NULL)find_cb(); else findedit->find_next_cb(); } //*********************************************** FindEdit::FindEdit( QWidget *parent, const char *name, Q3MultiLineEdit *edit ,QStatusBar *s) : QWidget( parent, name ,Qt::WDestructiveClose) { setCaption("Find"); // setMinimumSize(340,140); status = s; editor = edit; Q3BoxLayout *all = new Q3VBoxLayout(this,10); Q3BoxLayout *txt = new Q3HBoxLayout(all,4); QLabel *label = new QLabel("Find what:",this); txt->addWidget(label); find_field = new QLineEdit(this); find_field->setMinimumWidth(200); connect( find_field, SIGNAL(returnPressed()), SLOT(find_first_cb()) ); txt->addWidget(find_field); Q3BoxLayout *left1 = new Q3HBoxLayout(all,10); Q3ButtonGroup *direction = new Q3ButtonGroup(2,Qt::Vertical,"Dir",this); up = new QRadioButton("Up",direction); up->setChecked(false); down = new QRadioButton("Down",direction); down->setChecked(true); left1->addWidget(direction); Q3ButtonGroup *from = new Q3ButtonGroup(2,Qt::Vertical,"From",this); start = new QRadioButton("Start",from); start->setChecked(true); current = new QRadioButton("Current",from); current->setChecked(false); left1->addWidget(from); Q3GroupBox *type = new Q3GroupBox(2,Qt::Vertical,"Match",this); match_whole = new QCheckBox("Match exact",type); // box->addWidget(match_whole); match_case = new QCheckBox("Match case",type); // box->addWidget(match_case); left1->addWidget(type); Q3BoxLayout *right = new Q3VBoxLayout(left1,5); find_first = new QPushButton("Find",this); right->addWidget(find_first); connect( find_first, SIGNAL(clicked()), SLOT(find_first_cb()) ); find_next = new QPushButton("Find next",this); connect( find_next, SIGNAL(clicked()), SLOT(find_next_cb()) ); right->addWidget(find_next); cancel = new QPushButton("Cancel",this); connect( cancel, SIGNAL(clicked()), SLOT(cancel_cb()) ); right->addWidget(cancel); adjustSize(); curline=0; } //*********************************************** void FindEdit::find_first_cb() { if(current->isChecked()){ int line,col; editor->getCursorPosition(&line,&col); curline=line; } else if(down->isChecked()){ curline=0; } else{ curline=editor->numLines()-1; } find_next_cb(); } //*********************************************** void FindEdit::find_next_cb() { int k; QString str; QString w = find_field->text(); char *word = (char *)w.latin1(); int len = strlen(word); if(len==0)return; char *ptr,*ptr0,*ww,*ww0; int num=editor->numLines(); bool mwhole=match_whole->isChecked(); bool mcase=!(match_case->isChecked()); bool found; if(mcase)toLower(word); if(down->isChecked()){ if(curline<0)curline=0; for(;curlinetextLine(curline); ww = (char *)str.latin1(); ww0=ww; if(mcase)toLower(ww); if(mwhole){ ptr0=ww; found=false; do{ ptr=strstr(ptr0,word); if(!ptr)break; ptr0=ptr+len; if(ptr>ww && isalnum(*(ptr-1)))continue; if(isalnum(*ptr0))continue; found=true; }while(!found); if(!found)continue; } else{ if((ptr=strstr(ww,word))==NULL)continue; } k=int(ptr-ww); editor->setCursorPosition(curline,k,false); editor->setSelection(curline,k,curline,k+len); sprintf(tmp,"%d: %s",curline,ww0); status->message(tmp); curline++; return; } } else{ if(curline>=num)curline=num-1; for(;curline>=0;curline--){ str = editor->textLine(curline); ww = (char *)str.latin1(); ww0=ww; if(mcase)toLower(ww); if((ptr=strstr(ww,word))==NULL)continue; if(mwhole){ ptr0=ww; found=false; do{ ptr=strstr(ptr0,word); if(!ptr)break; ptr0=ptr+len; if(ptr>ww && isalnum(*(ptr-1)))continue; if(isalnum(*ptr0))continue; found=true; }while(!found); if(!found)continue; } else{ if((ptr=strstr(ww,word))==NULL)continue; } k=int(ptr-ww); editor->setCursorPosition(curline,k,false); editor->setSelection(curline,k,curline,k+len); sprintf(tmp,"%d: %s",curline,ww0); status->message(tmp); curline--; return; } } menu->errmes("Find","'%s' not found !",word); status->clear(); } //*********************************************** void FindEdit::cancel_cb() { hide(); status->clear(); } //***********************************************