#include #include #include #include #ifdef DMALLOC #include #endif #include "messages.h" #include "tcltk.h" #include "illist.h" #include "llist.h" #include "window.h" #include "channel.h" #include "quirc.h" void strlow(char *str) { int i; for ( i = 0; i < (signed)strlen(str) ; i++) str[i] = tolower(str[i]); } char *strstrnc(char *haystack, const char *needle) { char *h1; char *n1; char *result; long rv; h1 = strdup(haystack); n1 = strdup(needle); strlow(h1); strlow(n1); result = strstr(h1,n1); if (result) { rv = abs(h1 - result); free(h1); free(n1); return haystack + rv; } else { free(h1); free(n1); return NULL; } return NULL; } char *n_range(char *str, int a, int b) { char buffer[2048]= {0}; int i; if ( b > (signed)strlen(str) || a > b ) return strdup(""); for ( i = a ; i < b ; i++ ) { buffer[i - a] = str[i]; } buffer[i] = 0; return strdup(buffer); } list *complete(list &thelist, string &match, int ccase = 0, int stonly = 0) { list *lstst; // List containing strings from thelist which contain the substring match. list *lstok; // List containing strings from thelist which have match at the start of the string. string *strptr; string blah; char *pos; char *temp; char *mat; mat = strdup(match.c_str()); if (!ccase) strlow(mat); lstok = new list; lstst = new list; thelist.init_trav(); while ((strptr=thelist.trav())) { temp = strdup(strptr->c_str()); if (!ccase) strlow(temp); if ((pos=strstr(temp, mat))) { pos = (char*) (temp - pos); blah = *strptr; if (!pos) { lstst->insert_start(blah); } else { lstok->insert_start(blah); } } delete temp; } delete mat; if (lstst->getsize() || stonly ) { delete lstok; return lstst; } else { delete lstst; return lstok; } return NULL; } string expandmatch(list &thelist, const char *thesub, int ccase = 0, int stonly = 0) { char *tmpfull = 0; char *ptr = 0; char *strtmp = 0; char *sub = 0; char *newsub = 0; int lentw, lensub, i; list *tmplist; string stringtmp; string max; char *testword = 0; char *orig = 0; if (thelist.getsize() == 0) { max = thesub; return max; } thelist.init_trav(); testword = strdup(thelist.trav()->c_str()); if (thelist.getsize() == 1) { max = testword; } else { orig = strdup(testword); sub = strdup(thesub); if (!ccase) strlow(sub); if (!ccase) strlow(testword); lentw = strlen(testword); lensub = strlen(sub); max = sub; strtmp = new char[lentw+1]; tmpfull = testword; while (*tmpfull) { ptr = tmpfull = strstrnc(tmpfull,sub); if (tmpfull != testword && tmpfull != NULL) { i = 1; while((ptr - i + 1) != testword) { strncpy(strtmp,orig+abs(testword-(ptr-i)),i+lensub); //strncpy(strtmp,ptr-i,i+lensub); strtmp[lensub+i]=0; stringtmp = strtmp; tmplist = complete(thelist, stringtmp, ccase, stonly); if (thelist.getsize() == tmplist->getsize()) { max = stringtmp; } delete tmplist; i++; } } if (!tmpfull) break; tmpfull++; } newsub = strdup(max.c_str()); lensub = strlen(newsub); tmpfull = testword; while (*tmpfull) { ptr = tmpfull = strstrnc(tmpfull,newsub); if (tmpfull != NULL) { i = 1; while(*(ptr+i+lensub-1)) { //strncpy(strtmp,ptr,i+lensub); strncpy(strtmp,orig+abs(testword-(ptr)),i+lensub); strtmp[i+lensub]=0; stringtmp = strtmp; tmplist = complete(thelist, stringtmp, ccase, stonly); if (thelist.getsize() == tmplist->getsize()) { max = stringtmp; } delete tmplist; i++; } } if (!tmpfull) break; tmpfull++; } } if (sub) free (sub); if (strtmp) delete strtmp; if (newsub) free(newsub); if (testword) delete testword; if (orig) delete orig; return max; } int TT_Proc_complete(TT_PROC_OBJS) { list somelist; string somestring; string *strptr; list *newlst; Tcl_Obj *listptr; Tcl_Obj *objptr; int n; int lsize; int ccase; int stonly; string matchstr; Tcl_Obj **elems; if(objc!=5) { Tcl_SetResult(interp,"Usage: complete ",TCL_STATIC); return TCL_ERROR; } if (Tcl_ListObjGetElements(interp,objv[1],&lsize, &elems)!= TCL_OK) return TCL_ERROR; for (n=0;ninit_trav(); listptr=Tcl_NewListObj(0,0); while((strptr=newlst->trav())) { objptr=Tcl_NewStringObj((char *) strptr->c_str(),strlen(strptr->c_str())); if(Tcl_ListObjAppendElement(interp,listptr,objptr)==TCL_ERROR) return TCL_ERROR; } Tcl_SetObjResult(interp,listptr); delete newlst; return TCL_OK; } int TT_Proc_expandmatch(TT_PROC_OBJS) { list somelist; string somestring; string result; Tcl_Obj *objptr; int n; int lsize; int ccase; int stonly; string matchstr; Tcl_Obj **elems; if(objc!=5) { Tcl_SetResult(interp,"Usage: expandmatch ",TCL_STATIC); return TCL_ERROR; } if (Tcl_ListObjGetElements(interp,objv[1],&lsize, &elems)!= TCL_OK) return TCL_ERROR; for (n=0;n thelist; list *lstptr; string str; string rval; string tmpstr; string *strptr=0; twindow window; twindow *windowp; tchan channel; tchan *channelp; tnick *nickp; char colon[1000] = {0}; if (!strcmp(currentwindow,".main")) { if (origtext) free(origtext); if (aftertext) free(aftertext); if (matchtext) free(matchtext); if (befortext) free(befortext); return TCL_OK; } if (TT_IntF(TT_ARGS,"dcc_complete")) return TCL_OK; // Obtain the text and cursor position from the Tk widget // in which the completion key was pressed. origtext = strdup(TT_StrF(TT_ARGS,"%s.entry get",currentwindow)); origpos = (TT_IntF(TT_ARGS,"%s.entry index insert",currentwindow)); if (oldretrntext && !strcmp(origtext,oldretrntext) && oldpos == origpos) { if (origtext) free(origtext); origtext = strdup(oldorigtext); origpos = oldorigpos; cycle = 1; } else { oldorigpos = origpos; if (oldorigtext) free(oldorigtext); oldorigtext = strdup(origtext); } n = origpos; i = origpos; len = strlen(origtext); while ( i < len && origtext[i] != ' ') i++; if ( n > 0 ) { j = n; while ( j >= 0 && origtext[j-1] != ' ' && j > 0 ) j--; } else j = 0; befortext = n_range(origtext,0,j); matchtext = n_range(origtext,j,i); aftertext = n_range(origtext,i,len); str = matchtext; strcpy(window.pathname,currentwindow); windowp = windows.find(window); if (!strncmp(matchtext,"#",1)) { if ( !strncmp(currentwindow,".channel",8) && strlen(matchtext) == 1) { tmpstr = windowp->name; thelist.insert_start(tmpstr); } else { windowp->server->chanlist.init_trav(); while ( (channelp = windowp->server->chanlist.trav())) { tmpstr = channelp->name; thelist.insert_start(tmpstr); } } lstptr = complete(thelist, str, 0,1); if (lstptr->getsize()) { rval = expandmatch(*lstptr, str.c_str(),0,1); } if (lstptr->getsize() == 1) { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_postfix")); } } else if ( !strncmp(currentwindow,".channel",8)) { strcpy(channel.pathname,currentwindow); if ((channelp = windowp->server->chanlist.find(channel)) == NULL) { if (origtext) free(origtext); if (aftertext) free(aftertext); if (matchtext) free(matchtext); if (befortext) free(befortext); return TCL_OK; } channelp->nicklist.init_trav(); while ( (nickp=channelp->nicklist.trav()) ) { tmpstr = nickp->getname(); thelist.insert_start(tmpstr); } lstptr = complete(thelist, str, 0,0); lstptr->init_trav(); // while (strptr=lstptr->trav()) { //printf("%s\n", strptr->c_str()); //} if (lstptr->getsize()) { rval = expandmatch(*lstptr, str.c_str(),0,0); if (lstptr->getsize() == 1) { if ( j <=0 ) { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_seperator")); } else { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_postfix")); } } } } else if ( !strncmp(currentwindow,".status",7)) { tmpstr = windowp->server->getmynick(); thelist.insert_start(tmpstr); if (str == "") str = tmpstr; lstptr = complete(thelist, str, 0,0); if (lstptr->getsize()) { rval = expandmatch(*lstptr, str.c_str(),0,0); } if (lstptr->getsize() == 1) { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_postfix")); } } else if ( !strncmp(currentwindow,".chat",5)) { tmpstr = windowp->name + 1; if (str == "") str = tmpstr; thelist.insert_start(tmpstr); tmpstr = windowp->server->getmynick(); thelist.insert_start(tmpstr); lstptr = complete(thelist, str, 0,0); if (lstptr->getsize()) { rval = expandmatch(*lstptr, str.c_str(),0,0); } if ( j <=0 && lstptr->getsize() == 1) { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_seperator")); } else { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_postfix")); } } else if ( !strncmp(currentwindow,".query",6)) { tmpstr = windowp->name; if (str == "") str = tmpstr; thelist.insert_start(tmpstr); tmpstr = windowp->server->getmynick(); if (tmpstr != str) thelist.insert_start(tmpstr); lstptr = complete(thelist, str, 0,0); if (lstptr->getsize()) { rval = expandmatch(*lstptr, str.c_str(),0,0); } if (lstptr->getsize() == 1) { if (j <=0 ) { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_seperator")); } else { strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_postfix")); } } } else { fprintf(stderr,"Invalid window type encountered in completion code.\n"); exit(1); } rpos = strlen(rval.c_str()) + j + strlen(colon); if (rval == "") { rval = matchtext; rpos = origpos; } retrntext = (char *) malloc (strlen(befortext) + strlen(rval.c_str()) + strlen(aftertext) + strlen(colon) + 10); rpos = strlen(rval.c_str()) + j + strlen(colon); if (cycle && lstptr->getsize() > 0 && TT_Int(TT_ARGS,"set ::dynamic::nick_complete_cycle") == 1) { if (cycnum >= lstptr->getsize()) cycnum = 0; lstptr->init_trav(); for (int i = 0; i <= cycnum; i++) { strptr = lstptr->trav(); } if(cycnum<0) { fprintf(stderr,"cycnum is less than 0 in completion code.\n"); exit(1); } rval = strptr->c_str(); cycnum++; if ( j <=0 && strncmp(rval.c_str(),"#",1)) strcpy(colon,TT_Str(TT_ARGS,"set ::dynamic::nick_complete_seperator")); if (retrntext) free(retrntext); retrntext = (char *) malloc (strlen(befortext) + strlen(rval.c_str()) + strlen(aftertext) + strlen(colon) + 10); rpos = strlen(rval.c_str()) + j + strlen(colon); } strcpy(retrntext,befortext); strcat(retrntext,rval.c_str()); strcat(retrntext,colon); strcat(retrntext,aftertext); if (oldretrntext) free(oldretrntext); oldretrntext = strdup(retrntext); oldpos = rpos; TT_EvalF(TT_ARGS,"%s.entry delete 0 end",currentwindow); TT_EvalF(TT_ARGS,"%s.entry insert 0 %q",currentwindow, retrntext); TT_EvalF(TT_ARGS,"%s.entry icursor %d",currentwindow, rpos); if (lstptr) free(lstptr); if (aftertext) free(aftertext); if (origtext) free(origtext); if (matchtext) free(matchtext); if (befortext) free(befortext); if (retrntext) free(retrntext); return TCL_OK; } int TT_Proc_getpwents(TT_PROC_OBJS) { char *field; Tcl_Obj *listptr; Tcl_Obj *objptr; string *strptr; string temp; list *newlst; struct passwd *pwents; if(objc!=2) { Tcl_SetResult(interp,"Usage: getpwents ",TCL_STATIC); return TCL_ERROR; } if (!(field = strdup(Tcl_GetStringFromObj(objv[1],NULL)))) return TCL_ERROR; if (strcmp(field, "pw_name") && strcmp(field, "pw_passwd") && strcmp(field, "pw_uid") && strcmp(field, "pw_gid") && strcmp(field, "pw_gecos") && strcmp(field, "pw_dir") && strcmp(field, "pw_shell")) { Tcl_SetResult(interp,"Error: field must be one of: pw_name, pw_passwd, pw_uid, pw_gid, pw_dir, pw_shell, pw_gecos",TCL_STATIC); return TCL_ERROR; } newlst = new list; setpwent(); while ((pwents = getpwent())) { temp = pwents->pw_name; newlst->insert_start(temp); } endpwent(); newlst->init_trav(); listptr=Tcl_NewListObj(0,0); while((strptr=newlst->trav())) { objptr=Tcl_NewStringObj((char *) strptr->c_str(),strlen(strptr->c_str())); if(Tcl_ListObjAppendElement(interp,listptr,objptr)==TCL_ERROR) return TCL_ERROR; } Tcl_SetObjResult(interp,listptr); delete newlst; return TCL_OK; }