/* Search.c */ /*The routines in this module handle the search/replace functions of 'Liner*/ #include "Globals.h" #include "SearchWdws.h" #define MAYBE 2 #define NONONO 3 struct SearchParameters { char Search[80],Replace[80]; BYTE rep,cse,partial; }; struct SearchParameters parameters = { "","",FALSE,FALSE,TRUE }; struct Window *SearchWdw,*ReplAllWdw; GetSRParameters() /*Opens a window to get the parameters for Search/Replace*/ { int status; NewSearchWindow.Screen=(struct Screen *)Screen; SearchWdw=(struct Window *)OpenWindow(&NewSearchWindow); if(SearchWdw==NULL) { Leave(0,"Can't open the search/replace window!"); return(FALSE); } PrintIText(SearchWdw->RPort,&IntuiTextList1,0,0); ActivateGadget(&SearchFor,SearchWdw,NULL); /*Activate the Search for... text gadget*/ while((status=MonitorButtons())==NONONO); /*Let user enter info*/ if(status) /*OK, Cancel, or Wait*/ { parameters.rep = !((SrchRplc.Flags & SELECTED)==FALSE); parameters.partial = ((PartialWord.Flags & SELECTED)==FALSE); parameters.cse = !((CaseSensitive.Flags & SELECTED)==FALSE); strcpy(parameters.Search,SearchForSInfo.Buffer); strcpy(parameters.Replace,ReplaceWithSInfo.Buffer); if(status==MAYBE) status=FALSE; } else { /*Another gadget was toggled*/ strcpy(SearchForSInfo.Buffer,parameters.Search); strcpy(ReplaceWithSInfo.Buffer,parameters.Replace); SrchRplc.Flags = (parameters.rep) ? GADGHIMAGE+GADGIMAGE+SELECTED : GADGHIMAGE+GADGIMAGE; PartialWord.Flags = (parameters.partial) ? GADGHIMAGE+GADGIMAGE : GADGHIMAGE+GADGIMAGE+SELECTED; CaseSensitive.Flags = (parameters.cse) ? GADGHIMAGE+GADGIMAGE+SELECTED : GADGHIMAGE+GADGIMAGE; } CloseWindow(SearchWdw); return(status); } MonitorButtons() /*Monitor the IDCMP port*/ { ULONG Class; struct Gadget *gadg; struct IntuiMessage *mesg; for(;;) { Wait(1<UserPort->mp_SigBit); while((mesg=(struct IntuiMessage *)GetMsg(SearchWdw->UserPort))!=NULL) { Class=mesg->Class; /*Get the information*/ gadg=mesg->IAddress; ReplyMsg(mesg); /*Reply to the message*/ switch(Class) { case CLOSEWINDOW: /*Close gadget == CANCEL*/ return(FALSE); case GADGETUP: switch(gadg->GadgetID) { case 8: /*Cancel*/ return(FALSE); case 7: /*Wait*/ return(MAYBE); case 6: /*OK*/ return(TRUE); case 1: ActivateGadget(&ReplaceWith,SearchWdw,NULL); /*Activate the Replace with... string gadget when*/ /*the user presses RETURN in the Search for...*/ /*gadget*/ return(NONONO); /*Don't alter a flag :-) */ } } } } } extern struct LineItem *SearchText(Item,Pos,string,scase,partial) /*Search an outline for a particular string of characters*/ struct LineItem *Item; /*Item to start searching on*/ USHORT *Pos; /*Position in that item to start on*/ char *string; /*Search string*/ BYTE scase,partial; /*scase - TRUE if case matters, FALSE otherwise*/ /*partial-TRUE if it may be a part of a word*/ { int c,found,start,thestart; struct LineItem *cur,*theitem; BYTE status=FALSE; char chr,fchr; if(!scase) /*If case sensitive, convert the string to all uppercase*/ for(c=0;c= strlen(Item->Text)) /*If at the end of the line*/ { start=0; /*Start of next line*/ Item=(struct LineItem *)Item->NextItem; } else start=*Pos; /*Else, start at cursor position*/ for(cur=(struct LineItem *)Item;cur != NULL && !status;/*Search until end*/ cur=(struct LineItem *)cur->NextItem) /*or text is found*/ for(c=start;cText) && !status ;++c) { /*Loop that searches each line: */ start=0; if((partial) || ( (!partial) && ((c==0) || (cur->Text[c-1]==' ') ))) /*If partial words are OK, or if not, if the character*/ /*currently being checked is the first letter in a word*/ { if(!scase) /*If case is important*/ chr=toupper(cur->Text[c]); /*Switch to uppercase (see above)*/ else chr=cur->Text[c]; if(string[0]==chr) /*If first character matches...*/ { status=TRUE; theitem=(struct LineItem *)cur; thestart=c; for(found=1;foundText[c+found]); else fchr=cur->Text[c+found]; if(fchr!=string[found]) status=FALSE; } /*If the word is a prefix of another word*/ if(cur->Text[c+found] != ' ' && cur->Text[c+found]!= NULL && !partial) status = FALSE; /*return FALSE*/ } } } if(status) /*If found...*/ { *Pos=thestart; /*Return the position of the start of the text*/ return(theitem); /*And the item that it is found in*/ } /*(so that the cursor can be moved accordingly)*/ else return(NULL); /*Otherwise, nothing*/ } DoSearch(again,arexx) /*Main entry point for 'Search/Replace' and 'Next'*/ BYTE again,arexx; /*Again: TRUE if 'Next', FALSE if 'Search/Replace'*/ { char Buffer[8],reslt[160],preservation[80]; int status; UBYTE TempY; struct LineItem *tempitem,*result; struct LineItem *firstitem=(struct LineItem *)CurrentItem; USHORT Pos=(again && again != 100) ? CurX-MinX(CurrentItem)+1 : CurX-MinX(CurrentItem); status = (again) ? TRUE : GetSRParameters(); /*If 'Next', search no matter what. Otherwise, depends on user*/ CancelInvs(); /*Cancel text highlighting*/ if(ErrorInTitle) /*Cancel any errors in the title bar*/ TitleErrorCancel(); if(status) /*If it's OK to search*/ { strcpy(preservation,parameters.Search); /*Store the search string*/ /*so if SearchText turns it to all caps, we'll still have the*/ /*original*/ result=(struct LineItem *) /*Search the text*/ SearchText(CurrentItem,&Pos,parameters.Search,parameters.cse, parameters.partial); if(result!=NULL) /*If found...*/ { /*Place the cursor at the start of the word*/ if(result!=FirstScrnItem || result!=firstitem) { FirstScrnItem=CurrentItem=(struct LineItem *)result; PrintItemList(CurrentItem,1); } PlotCursor(MinX(CurrentItem)+Pos,1); if(parameters.rep) /*If a search and replace*/ { /*Replace!!!!*/ strcpy(reslt,&(CurrentItem->Text[Pos+strlen(parameters.Search)])); strins(reslt,parameters.Replace); CurrentItem->Text[Pos]=NULL; strins(reslt,CurrentItem->Text); /*Break the line apart if necessary*/ tempitem=(struct LineItem *)BreakLineApart(CurrentItem, CurrentItem->NextItem,reslt); PlotCursor(1,CurY); Buffer[0]=CSI; Buffer[1]=0x4b; WriteConsole(Buffer,2); TempY=CurY; if(tempitem==CurrentItem) PrintItem(CurrentItem); else PrintItemList(CurrentItem,CurY); PlotCursor(MinX(CurrentItem)+Pos,TempY); CheckModified(); /*Text has been modified*/ } strcpy(parameters.Search,preservation); return(TRUE); } else /*If it wasn't found*/ { strcpy(parameters.Search,preservation); if(!arexx) /*If this wasn't an ARexx command*/ TitleError("Wasn't found!!!"); return(FALSE); } } } void ModifyParams(search,replace,case_s,partial,s_repl) char *search,*replace; BYTE case_s,partial,s_repl; { if(search[0]!=NULL) strcpy(parameters.Search,search); if(replace[0]!=NULL) strcpy(parameters.Replace,replace); if(case_s!=100) parameters.cse=case_s; if(partial!=100) parameters.partial=partial; if(s_repl!=100) parameters.rep=s_repl; } void ReplaceAll(verify) /*Search/replace entire document at once*/ BYTE verify; { BYTE stat; if(verify) { ModifyParams("","",100,100,FALSE); while(DoSearch(TRUE,TRUE)) /*Search for text*/ { if(stat=AskChange()) /*Ask user what to do*/ { if(stat==TRUE) /*Replace*/ { ModifyParams("","",100,100,TRUE); DoSearch(100,TRUE); ModifyParams("","",100,100,FALSE); } /*Else goto next*/ } else return; /*Else cancel*/ } TitleError("No more found"); } else /*Do all without verification*/ { ModifyParams("","",100,100,TRUE); while(DoSearch(TRUE,TRUE)); } } BYTE AskChange() /*Ask user if he wants to do replace*/ { struct Window *ReplAllWdw; struct IntuiMessage *mesg; struct Gadget *gadg; NewWindowStructure2.Screen=(struct Screen *)Screen; /*'Liner screen*/ if((ReplAllWdw=(struct Window *)OpenWindow(&NewWindowStructure2))==NULL) return(FALSE); /*Open the window*/ PrintIText(ReplAllWdw->RPort,&IntuiTextList2,0,0); Wait(1<UserPort->mp_SigBit); /*Wait for gadget press*/ if((mesg=(struct IntuiMessage *)GetMsg(ReplAllWdw->UserPort))==NULL) { CloseWindow(ReplAllWdw); return(FALSE); /*Get the message*/ } gadg=(struct Gadget *)mesg->IAddress;/*Get the gadget structure's addr*/ ReplyMsg(mesg); /*Reply to it*/ CloseWindow(ReplAllWdw); /*Close the window*/ return(gadg->GadgetID); /*Return the gadget ID*/ } /*End of Search.c*/