1 #include <ctype.h>
2 #include <sys/time.h>
3 #include <unistd.h>
4 #include <sys/socket.h>
5 
6 #ifdef DMALLOC
7 #include <dmalloc.h>
8 #endif
9 
10 #include "tcltk.h"
11 #include "window.h"
12 #include "quirc.h"
13 #include "format.h"
14 #include "messages.h"
15 #include "echo.h"
16 #include "command.h"
17 #include "tags.h"
18 #include "mytcl.h"
19 
20 
21 time_t lastcommand;
22 
23 
TT_Proc_activebutton(TT_PROC_ARGS)24 int TT_Proc_activebutton(TT_PROC_ARGS) {
25   twindow window;
26   twindow *windowp;
27   strcpy(window.pathname,argv[1]);
28   windowp=windows.find(window);
29   if(windowp) TT_EvalF(TT_ARGS,
30 		       "QListBox::colorize .windowlist %d active",
31 		       windowp->index);
32   return TCL_OK;
33 }
34 
TT_Proc_bgerror(TT_PROC_ARGS)35 int TT_Proc_bgerror(TT_PROC_ARGS) {
36   static int inbgerror;
37   char *result;
38   int wasinbgerror=inbgerror;
39   int baderror=0;
40 
41   if(!inbgerror && TT_Int(TT_ARGS,"set ::internal::done_main_window")) {
42     inbgerror=1;
43     if(!(result=fparse("ERROR_INFO",-1,1,TT_Str(TT_ARGS,"set errorInfo")))) {
44       baderror=1;
45     }
46     if(!baderror) {
47       echo(result,".main",1);
48       if(!(result=fparse("ERROR_CODE",-1,1,TT_Str(TT_ARGS,"set errorCode")))) {
49 	baderror=1;
50       }
51     }
52     if(!baderror) {
53       echo(result,".main",1);
54       if(!(result=fparse("ERROR_ADDITIONAL",-1,1,argv[1]))) {
55 	baderror=1;
56       }
57     }
58     if(!baderror) {
59       echo(result,".main",1);
60     }
61     inbgerror=0;
62   }
63   if(wasinbgerror) {
64     fprintf(stderr,"********************************************************************************\n");
65     fprintf(stderr,M_ERROR_INFINITE_LOOP);
66     fprintf(stderr,"********************************************************************************\n");
67   }
68   if(baderror) {
69     fprintf(stderr,M_ERROR_NO_FORMAT);
70   }
71   if(baderror || wasinbgerror || !TT_Int(TT_ARGS,"set ::internal::done_main_window")) {
72     fprintf(stderr,"%s:\n%s\n",M_ERROR_INFO,TT_Str(TT_ARGS,"set errorInfo"));
73     fprintf(stderr,"%s: %s\n",M_ERROR_CODE,TT_Str(TT_ARGS,"set errorCode"));
74     if(argc==2) {
75       fprintf(stderr,"%s: %s\n",M_ERROR_ADDITIONAL,argv[1]);
76     }
77     exit(1);
78   }
79   return TCL_OK;
80 }
81 
TT_Proc_callproc(TT_PROC_ARGS)82 int TT_Proc_callproc(TT_PROC_ARGS) {
83   // argv[1] is the proc name
84   // argv[2] is the list of arguments to the proc
85   // argv[3] is the server index
86   if(argc!=4) {
87     Tcl_SetResult(interp,"Usage: callproc <procname> <argument_list> <server_index>",TCL_VOLATILE);
88     return TCL_ERROR;
89   }
90   TT_EvalF(TT_ARGS,"%s %s %s",argv[1],argv[3],argv[2]);
91   return TCL_OK;
92 }
93 
TT_Proc_channel(TT_PROC_ARGS)94 int TT_Proc_channel(TT_PROC_ARGS) {
95   twindow window;
96   twindow *windowp;
97   strcpy(window.pathname,currentwindow);
98   if((windowp=windows.find(window))) {
99     if(!strncmp(windowp->pathname,".channel",8)) {
100       Tcl_SetResult(interp,windowp->name,TCL_VOLATILE);
101     }
102   }
103   return TCL_OK;
104 }
105 
TT_Proc_configtags(TT_PROC_ARGS)106 int TT_Proc_configtags(TT_PROC_ARGS) {
107   configuretags(argv[1],argv[2],argv[3]);
108   return TCL_OK;
109 }
110 
TT_Proc_connect(TT_PROC_ARGS)111 int TT_Proc_connect(TT_PROC_ARGS) {
112   twindow window;
113   twindow *windowp;
114   if(argc>2) {
115     Tcl_SetResult(interp,"Usage: connect [<serverindex>]",TCL_VOLATILE);
116     return TCL_ERROR;
117   }
118   if(argc==1) {
119     strcpy(window.pathname,currentwindow);
120   } else {
121     sprintf(window.pathname,".status%s",argv[1]);
122   }
123   if((windowp=windows.find(window))&&windowp->server) {
124     windowp->server->do_connect();
125   }
126   return TCL_OK;
127 }
128 
TT_Proc_closewindow(TT_PROC_ARGS)129 int TT_Proc_closewindow(TT_PROC_ARGS) {
130   tchan chan;
131   tchan *chanp;
132   tquery query;
133   tserver *serverp;
134   char temp[TEMPLEN];
135   twindow window;
136   twindow *windowp;
137   int newindex;
138 
139   if(argc!=2) {
140     Tcl_SetResult(interp,"Usage: closewindow <pathname>",TCL_STATIC);
141     return TCL_ERROR;
142   }
143   if(strcmp(argv[1],".main")) {
144     strcpy(window.pathname,argv[1]);
145     if((windowp=windows.find(window))) {
146       newindex=windowp->index-1;
147       if(!strncmp(argv[1],".query",6)) {
148 	TT_EvalF(TT_ARGS,"destroy %s",argv[1]);
149 	strcpy(query.pathname,argv[1]);
150 	windowp->server->querylist.deleteitem(query);
151 	TT_EvalF(TT_ARGS,"QListBox::delete .windowlist %d",windowp->index);
152 	windows.deleteitem(window);
153 	TT_EvalF(TT_ARGS,"totop %d",newindex);
154       }
155       if(!strncmp(argv[1],".chat",5)) {
156 	windowp->dcc->disconnect();
157 	TT_EvalF(TT_ARGS,"destroy %s",argv[1]);
158 	TT_EvalF(TT_ARGS,"QListBox::delete .windowlist %d",windowp->index);
159 	delete windowp->dcc;
160 	windows.deleteitem(window);
161 	TT_EvalF(TT_ARGS,"totop %d",newindex);
162       }
163       if(!strncmp(argv[1],".files",6)) {
164 	if(windowp->server->dcclist.lastindex()==-1) {
165 	  //windowp->dcc->disconnect();
166 	  TT_EvalF(TT_ARGS,"destroy %s",argv[1]);
167 	  TT_EvalF(TT_ARGS,"QListBox::delete .windowlist %d",windowp->index);
168 	  //delete windowp->dcc;
169 	  windows.deleteitem(window);
170 	  TT_EvalF(TT_ARGS,"totop %d",newindex);
171 	}
172       }
173       if(!strncmp(argv[1],".channel",8)) {
174 	TT_EvalF(TT_ARGS,"destroy %s",argv[1]);
175 	strcpy(chan.pathname,argv[1]);
176 	if((chanp=windowp->server->chanlist.find(chan))) {
177 	  if(chanp->ison) {
178 	    sprintf(temp,"PART %s",chanp->name);
179 	    // DEBUG
180 	    //TT_EvalF(TT_ARGS,".raw.text insert end \"Command (tcl.cc:173): %q\\n\"",temp);
181 	    windowp->server->senddata(temp);
182 	  }
183 	  windowp->server->chanlist.deleteitem(chan);
184 	}
185 	TT_EvalF(TT_ARGS,"QListBox::delete .windowlist %d",windowp->index);
186 	windows.deleteitem(window);
187 	TT_EvalF(TT_ARGS,"totop %d",newindex);
188       }
189       if(!strncmp(argv[1],".status",7)) {
190 	if(windowp->server->dcclist.lastindex()==-1) {
191 	  serverp=windowp->server;
192 	  if(serverp->connected) serverp->disconnect(1);
193 	  windows.init_trav();
194 	  while((windowp=windows.trav())) {
195 	    if(serverp==windowp->server) {
196 	      if(!strncmp(windowp->pathname,".chat",5)) {
197 		windowp->dcc->disconnect();
198 	      }
199 	      strcpy(window.pathname,windowp->pathname);
200 	      TT_EvalF(TT_ARGS,"destroy %s",windowp->pathname);
201 	      if((windowp=windows.find(window))) TT_EvalF(TT_ARGS,"QListBox::delete .windowlist %d",windowp->index);
202 	      windows.deleteitem(window);
203 	    }
204 	  }
205 	  delete serverp;
206 	  TT_EvalF(TT_ARGS,"totop %d",newindex);
207 	}
208       }
209     }
210   } else {
211     TT_EvalF(TT_ARGS,"\
212       %s.text configure -state normal\n\
213       %s.text delete 0.0 end\n\
214       for { set n 0 } { $n < $::dynamic::blank_lines_before_text } { incr n } {\n\
215 	%s.text insert end \\n\n\
216       }\n\
217       %s.text configure -state disabled\n\
218       %s.text yview moveto 1\
219     ",argv[1],argv[1],argv[1],argv[1],argv[1]);
220   }
221   return TCL_OK;
222 }
223 
TT_Proc_currentindex(TT_PROC_ARGS)224 int TT_Proc_currentindex(TT_PROC_ARGS) {
225   twindow window;
226   twindow *windowp;
227   strcpy(window.pathname,currentwindow);
228   Tcl_SetResult(interp,"-1",TCL_VOLATILE);
229   if((windowp=windows.find(window))) {
230     if(windowp->server) {
231       Tcl_SetResult(interp,strnum(windowp->server->index),TCL_VOLATILE);
232     }
233   }
234   return TCL_OK;
235 }
236 
TT_Proc_currentwindow(TT_PROC_ARGS)237 int TT_Proc_currentwindow(TT_PROC_ARGS) {
238   Tcl_SetResult(interp,currentwindow,TCL_VOLATILE);
239   return TCL_OK;
240 }
241 
TT_Proc_disconnect(TT_PROC_ARGS)242 int TT_Proc_disconnect(TT_PROC_ARGS) {
243   twindow window;
244   twindow *windowp;
245   if(argc>2) {
246     Tcl_SetResult(interp,"Usage: disconnect [<serverindex>]",TCL_VOLATILE);
247     return TCL_ERROR;
248   }
249   if(argc==1) {
250     strcpy(window.pathname,currentwindow);
251   } else {
252     sprintf(window.pathname,".status%s",argv[1]);
253   }
254   if((windowp=windows.find(window))&&windowp->server) {
255     windowp->server->disconnect(1);
256   } else {
257     Tcl_SetResult(interp,"Usage: disconnect [<serverindex>]",TCL_VOLATILE);
258     return TCL_ERROR;
259   }
260   return TCL_OK;
261 }
262 
TT_Proc_echo(TT_PROC_OBJS)263 int TT_Proc_echo(TT_PROC_OBJS) {
264   int listc;
265   char **listv;
266   int n,i;
267   if(objc>4||objc<2) {
268     Tcl_SetResult(interp,"Usage: echo <text> [<pathname>] [<activate_windowlist>]",TCL_STATIC);
269     return TCL_ERROR;
270   }
271   if((objc==4)&&((!strcmp(ARGV(2),"0"))||(!strcmp(ARGV(2),"1")))) {
272     // echo pathname activate text
273     echo_n(objv[3],ARGV(1),atoi(ARGV(2)));
274   } else {
275     if(objc==2) {
276       // echo text
277       if(strlen(currentwindow)) echo_n(objv[1],currentwindow,0);
278       return TCL_OK;
279     }
280     if(objc==3) n=1; else n=atoi(ARGV(3));
281     // echo text pathname [activate]
282     if(Tcl_SplitList(interp,ARGV(2),&listc,(const char ***)&listv)==TCL_ERROR)
283       return TCL_ERROR;
284     for(i=0;i<listc;i++) {
285       // The old server specific echo used to check if windows existed
286       echo_n(objv[1],listv[i],n);
287     }
288     Tcl_Free((char *)listv);
289   }
290   return TCL_OK;
291 }
292 
TT_Proc_echotags(TT_PROC_OBJS)293 int TT_Proc_echotags(TT_PROC_OBJS) {
294   int listc;
295   char **listv;
296   int n,i;
297   char *tempstring;
298   if(objc>4||objc<2) {
299     Tcl_SetResult(interp,"Usage: echotags <text> [<pathname>] [<activate_windowlist>]",TCL_STATIC);
300     return TCL_ERROR;
301   }
302   if(objc==2) {
303     // echotags text
304     if(strlen(currentwindow)) echotags(objv[1],currentwindow,0);
305     return TCL_OK;
306   }
307   if(objc==3) n=1; else n=atoi(ARGV(3));
308 
309   // echotags text pathname [activate]
310   tempstring = mystrdup(ARGV(2));
311   if(Tcl_SplitList(interp,
312 		   tempstring,
313 		   &listc,
314 		   (const char ***)&listv)==TCL_ERROR) {
315     free(tempstring);
316     return TCL_ERROR;
317   }
318   free(tempstring);
319   for(i=0;i<listc;i++) {
320     echotags(objv[1],listv[i],n);
321   }
322   Tcl_Free((char *)listv);
323   return TCL_OK;
324 }
325 
TT_Proc_escape(TT_PROC_OBJS)326 int TT_Proc_escape(TT_PROC_OBJS) {
327   int length;
328   Tcl_Obj *objptr;
329   char *dst;
330   char *currentpiece;
331   int flags;
332   if(objc!=2) {
333     Tcl_SetResult(interp,"usage: escape <data>",TCL_STATIC);
334     return TCL_ERROR;
335   }
336   currentpiece=Tcl_GetStringFromObj(objv[1],&length);
337   dst=(char *)malloc(Tcl_ScanCountedElementFixed(currentpiece,length,&flags));
338   flags|=TCL_DONT_USE_BRACES;
339   length=Tcl_ConvertCountedElement(currentpiece, length, dst, flags);
340   objptr=Tcl_NewStringObj(dst,length);
341   free(dst);
342   Tcl_SetObjResult(interp,objptr);
343   return TCL_OK;
344 }
345 
TT_Proc_exit(TT_PROC_ARGS)346 int TT_Proc_exit(TT_PROC_ARGS) {
347   //foreach server [servers] {
348   //::template::quote $server \"QUIT :$::dynamic::default_quit\"
349   //}
350   TT_Eval(TT_ARGS,"\
351     shutdown\n\
352     die\n\
353   ");
354   return TCL_OK;
355 }
356 
TT_Proc_fdisplay(TT_PROC_ARGS)357 int TT_Proc_fdisplay(TT_PROC_ARGS) {
358   if(argc<2) {
359     Tcl_SetResult(interp,"Usage: fdisplay <type> [arguments]",TCL_STATIC);
360     return TCL_ERROR;
361   }
362   if(!fexists(argv[1])) {
363     Tcl_SetResult(interp,"fdisplay: Invalid format type.",TCL_STATIC);
364     return TCL_ERROR;
365   }
366   fdisplayv(argv[1],-1,argc-2,&argv[2]);
367   return TCL_OK;
368 }
369 
TT_Proc_fgetformat(TT_PROC_ARGS)370 int TT_Proc_fgetformat(TT_PROC_ARGS) {
371   if(argc<2) {
372     Tcl_SetResult(interp,"Usage: fgetformat <type>",TCL_STATIC);
373     return TCL_ERROR;
374   }
375   if(!fexists(argv[1])) {
376     Tcl_SetResult(interp,"fdisplay: Invalid format type.",TCL_STATIC);
377     return TCL_ERROR;
378   }
379   Tcl_SetResult(interp,fgetformat(argv[1]),TCL_VOLATILE);
380   return TCL_OK;
381 }
382 
TT_Proc_fgetpathnames(TT_PROC_ARGS)383 int TT_Proc_fgetpathnames(TT_PROC_ARGS) {
384   if(argc<2) {
385     Tcl_SetResult(interp,"Usage: fgetpathnames <type> [arguments]",TCL_STATIC);
386     return TCL_ERROR;
387   }
388   if(!fexists(argv[1])) {
389     Tcl_SetResult(interp,"fgetpathnames: Invalid format type.",TCL_STATIC);
390     return TCL_ERROR;
391   }
392   Tcl_SetResult(interp,fgetpathnames(argv[1],-1,argc-2,&argv[2]),TCL_VOLATILE);
393   return TCL_OK;
394 }
395 
TT_Proc_flocation(TT_PROC_ARGS)396 int TT_Proc_flocation(TT_PROC_ARGS) {
397   char assemble[TEMPLEN];
398   if(argc!=2 && argc!=3) {
399     Tcl_SetResult(interp,"Usage: flocation <type> [argument]",TCL_STATIC);
400     return TCL_ERROR;
401   }
402   if(!strcasecmp(argv[1],"main")) {
403     Tcl_SetResult(interp,".main",TCL_STATIC);
404     return TCL_OK;
405   }
406   if(!strcasecmp(argv[1],"current")) {
407     Tcl_SetResult(interp,"[currentwindow]",TCL_STATIC);
408     return TCL_OK;
409   }
410   if(!strcasecmp(argv[1],"status")) {
411     Tcl_SetResult(interp,"[pathname status]",TCL_STATIC);
412     return TCL_OK;
413   }
414   if(!strcasecmp(argv[1],"currentorstatus")) {
415     Tcl_SetResult(interp,"[if { [currentindex]==[index] } { set ::internal::junk [currentwindow] } else { set ::internal::junk [pathname status] }]",TCL_STATIC);
416     return TCL_OK;
417   }
418   if(!strcasecmp(argv[1],"serverall")) {
419     Tcl_SetResult(interp,"[pathname all]",TCL_STATIC);
420     return TCL_OK;
421   }
422   if(!strcasecmp(argv[1],"files")) {
423     Tcl_SetResult(interp,"[pathname files]",TCL_STATIC);
424     return TCL_OK;
425   }
426   if(!strcasecmp(argv[1],"all")) {
427     Tcl_SetResult(interp,"[windows]",TCL_STATIC);
428     return TCL_OK;
429   }
430   if(!strcasecmp(argv[1],"none")) {
431     Tcl_SetResult(interp,"",TCL_STATIC);
432     return TCL_OK;
433   }
434   if(!strcasecmp(argv[1],"onchannel") && argc==3) {
435     sprintf(assemble,"onchannel %s",argv[2]);
436     Tcl_SetResult(interp,assemble,TCL_VOLATILE);
437     return TCL_OK;
438   }
439   if(!strcasecmp(argv[1],"channelorstatus") && argc==3) {
440     sprintf(assemble,"channelorstatus %s",argv[2]);
441     Tcl_SetResult(interp,assemble,TCL_VOLATILE);
442     return TCL_OK;
443   }
444   if(!strcasecmp(argv[1],"pathname") && argc==3) {
445     sprintf(assemble,"pathname %s",argv[2]);
446     Tcl_SetResult(interp,assemble,TCL_VOLATILE);
447     return TCL_OK;
448   }
449   if(!strcasecmp(argv[1],"chat") && argc==3) {
450     sprintf(assemble,"chat %s",argv[2]);
451     Tcl_SetResult(interp,assemble,TCL_VOLATILE);
452     return TCL_OK;
453   }
454   Tcl_SetResult(interp,"flocation: Invalid type or too few arguments.",TCL_STATIC);
455   return TCL_ERROR;
456 }
457 
TT_Proc_fparse(TT_PROC_ARGS)458 int TT_Proc_fparse(TT_PROC_ARGS) {
459   // fparse <type> [arguments]
460   // 0      1      2+
461   // argc 1 2      3
462   char *result;
463   if(argc<2) {
464     Tcl_SetResult(interp,"Usage: fparse <type> [arguments]",TCL_STATIC);
465     return TCL_ERROR;
466   }
467   if(!fexists(argv[1])) {
468     Tcl_SetResult(interp,"fparse: Invalid format type.",TCL_STATIC);
469     return TCL_ERROR;
470   }
471   if(!(result=fparsev(argv[1],-1,argc-2,&argv[2]))) {
472     Tcl_SetResult(interp,"fparse: Error parsing format (No argument present for format argument number?).",TCL_STATIC);
473     return TCL_ERROR;
474   }
475   Tcl_SetResult(interp,result,TCL_VOLATILE);
476   return TCL_OK;
477 }
478 
TT_Proc_fset(TT_PROC_ARGS)479 int TT_Proc_fset(TT_PROC_ARGS) {
480   if(argc<3 || argc>5) {
481     Tcl_SetResult(interp,"Usage: fset <type> <format> [location [activate]]",TCL_STATIC);
482     return TCL_ERROR;
483   }
484   hash_set(&formats,argv[1],argv[2]);
485   if(argc<5) hash_set(&activate,argv[1],"1"); else hash_set(&activate,argv[1],argv[4]);
486   if(argc>3) {
487     hash_set(&locations,argv[1],argv[3]);
488   } else {
489     hash_set(&locations,argv[1],".main");
490   }
491   return TCL_OK;
492 }
493 
TT_Proc_gettags(TT_PROC_OBJS)494 int TT_Proc_gettags(TT_PROC_OBJS) {
495   Tcl_Obj *result;
496   char *pathname;
497   if(objc>3||objc<2) {
498     Tcl_SetResult(interp,"Usage: gettags <text> [<pathname>]",TCL_STATIC);
499     return TCL_ERROR;
500   }
501   if(objc==2) {
502     // gettags text
503     pathname=currentwindow;
504   } else {
505     // gettags text pathname
506     pathname=ARGV(2);
507   }
508   if(!strlen(pathname)) {
509     Tcl_SetResult(interp,"Usage: gettags <text> [<pathname>]  (Pathname cannot be an empty string.)",TCL_STATIC);
510     return TCL_ERROR;
511   }
512   result=gettags(objv[1],pathname);
513   Tcl_SetObjResult(interp,result);
514   Tcl_DecrRefCount(result);
515   return TCL_OK;
516 }
517 
TT_Proc_hist(TT_PROC_ARGS)518 int TT_Proc_hist(TT_PROC_ARGS) {
519   tcommand *commandp;
520   char assemble[TEMPLEN];
521   history.init_trav();
522   while((commandp=history.trav())) {
523     sprintf(assemble," \0030,14 HISTORY \003 %d:  %s",commandp->index,commandp->line);
524     echo(assemble,currentwindow,1);
525   }
526   return TCL_OK;
527 }
528 
TT_Proc_histdown(TT_PROC_ARGS)529 int TT_Proc_histdown(TT_PROC_ARGS) {
530   tcommand command;
531   tcommand *commandp;
532   if(historyposition!=-1) {
533     if(historyposition==0) {
534       TT_EvalF(TT_ARGS,"%s.entry delete 0 end",currentwindow);
535       TT_EvalF(TT_ARGS,"%s.entry insert 0 %q",currentwindow,historycommand);
536       if(historycommand) free(historycommand);
537       historycommand=0;
538       historyposition--;
539     } else {
540       historyposition--;
541       TT_EvalF(TT_ARGS,"%s.entry delete 0 end",currentwindow);
542       command.index=historyposition;
543       commandp=history.find(command);
544       TT_EvalF(TT_ARGS,"%s.entry insert 0 %q",currentwindow,commandp->line);
545     }
546   }
547   return TCL_OK;
548 }
549 
TT_Proc_histup(TT_PROC_ARGS)550 int TT_Proc_histup(TT_PROC_ARGS) {
551   tcommand command;
552   tcommand *commandp;
553   if((historyposition!=99)&&(historyposition<history.lastindex())) {
554     if(historyposition==-1) {
555       historycommand=strdup(TT_StrF(TT_ARGS,"%s.entry get",currentwindow));
556     }
557     historyposition++;
558     TT_EvalF(TT_ARGS,"%s.entry delete 0 end",currentwindow);
559     command.index=historyposition;
560     commandp=history.find(command);
561     TT_EvalF(TT_ARGS,"%s.entry insert 0 %q",currentwindow,commandp->line);
562   }
563   return TCL_OK;
564 }
565 
TT_Proc_idle(TT_PROC_ARGS)566 int TT_Proc_idle(TT_PROC_ARGS) {
567   if(!lastcommand) {
568     Tcl_SetResult(interp,"0",TCL_STATIC);
569   } else {
570     Tcl_SetResult(interp,strnum(time(0)-lastcommand),TCL_VOLATILE);
571   }
572   return TCL_OK;
573 }
574 
TT_Proc_index(TT_PROC_ARGS)575 int TT_Proc_index(TT_PROC_ARGS) {
576   if(argc!=1) {
577     Tcl_SetResult(interp,"Usage: index",TCL_VOLATILE);
578     return TCL_ERROR;
579   }
580   Tcl_SetResult(interp,"-1",TCL_VOLATILE);
581   return TCL_OK;
582 }
583 
TT_Proc_ischannel(TT_PROC_ARGS)584 int TT_Proc_ischannel(TT_PROC_ARGS) {
585   if(argc>=2) {
586     if(ischannel(argv[1]))
587       Tcl_SetResult(interp,"1",TCL_VOLATILE);
588     else
589       Tcl_SetResult(interp,"0",TCL_VOLATILE);
590   }
591   return TCL_OK;
592 }
593 
TT_Proc_memory(TT_PROC_ARGS)594 int TT_Proc_memory(TT_PROC_ARGS) {
595   twindow *windowp;
596   int count=0;
597   windows.init_trav();
598   while((windowp=windows.trav())) {
599     count+=TT_IntF(TT_ARGS,"\
600       set all [%s.text dump -text 0.0 end]\n\
601       set ::internal::count 0\n\
602       for { set n 0 } { $n < [llength $all] } { incr n } {\n\
603         if { [lindex $all $n]==\"text\" } {\n\
604           incr ::internal::count [string length [lindex $all [expr $n+1]]]\n\
605         }\n\
606       }\n\
607       echo \"Characters in %s: $::internal::count\"\n\
608       set ::internal::count\n\
609     ",windowp->pathname,windowp->pathname);
610   }
611   count+=TT_Int(TT_ARGS,"\
612     set all [.raw.text dump -text 0.0 end]\n\
613     set ::internal::count 0\n\
614     for { set n 0 } { $n < [llength $all] } { incr n } {\n\
615       if { [lindex $all $n]==\"text\" } {\n\
616         incr ::internal::count [string length [lindex $all [expr $n+1]]]\n\
617       }\n\
618     }\n\
619     echo \"Characters in .raw: $::internal::count\"\n\
620     set ::internal::count\n\
621   ");
622   TT_EvalF(TT_ARGS,"echo \"Total Characters: %d (*3=%d)\"",count,count*3);
623   TT_Eval(TT_ARGS,"echo \"Memory usage: [lindex [exec cat /proc/[pid]/stat] 22]\"");
624   TT_EvalF(TT_ARGS,"echo \"Memory Usage minus Total Predicted: [expr [lindex [exec cat /proc/[pid]/stat] 22]-%d]\"",count*3);
625   /*
626   struct rusage usage;
627   if(getrusage(RUSAGE_SELF,&usage)==-1) {
628     perror("getrusage()");
629     exit(1);
630   }
631   printf("user time used: %ld and %ld\n",usage.ru_utime.tv_sec,usage.ru_utime.tv_usec);
632   printf("system time used: %ld and %ld\n",usage.ru_stime.tv_sec,usage.ru_stime.tv_usec);
633   printf("maximum resident set size: %ld\n",usage.ru_maxrss);
634   printf("integral shared memory size: %ld\n",usage.ru_ixrss);
635   printf("integral unshared data size: %ld\n",usage.ru_idrss);
636   printf("integral unshared stack size: %ld\n",usage.ru_isrss);
637   printf("page reclaims: %ld\n",usage.ru_minflt);
638   printf("page faults: %ld\n",usage.ru_majflt);
639   printf("swaps: %ld\n",usage.ru_nswap);
640   printf("block input operations: %ld\n",usage.ru_inblock);
641   printf("block output operations: %ld\n",usage.ru_oublock);
642   printf("messages sent: %ld\n",usage.ru_msgsnd);
643   printf("messages received: %ld\n",usage.ru_msgrcv);
644   printf("signals received: %ld\n",usage.ru_nsignals);
645   printf("voluntary context switches: %ld\n",usage.ru_nvcsw);
646   printf("involuntary context switches: %ld\n",usage.ru_nivcsw);
647   */
648   //struct timeval ru_utime; /* user time used */
649   //struct timeval ru_stime; /* system time used */
650   //long ru_maxrss;          /* maximum resident set size */
651   //long ru_ixrss;      /* integral shared memory size */
652   //long ru_idrss;      /* integral unshared data size */
653   //long ru_isrss;      /* integral unshared stack size */
654   //long ru_minflt;          /* page reclaims */
655   //long ru_majflt;          /* page faults */
656   //long ru_nswap;      /* swaps */
657   //long ru_inblock;         /* block input operations */
658   //long ru_oublock;         /* block output operations */
659   //long ru_msgsnd;          /* messages sent */
660   //long ru_msgrcv;          /* messages received */
661   //long ru_nsignals;        /* signals received */
662   //long ru_nvcsw;      /* voluntary context switches */
663   //long ru_nivcsw;          /* involuntary context switches */
664   return TCL_OK;
665 }
666 
TT_Proc_microtime(TT_PROC_ARGS)667 int TT_Proc_microtime(TT_PROC_ARGS) {
668   struct timeval tv;
669   struct timezone tz;
670   char temptime[100];
671   tz.tz_minuteswest=0;
672   tz.tz_dsttime=0;
673   if(gettimeofday(&tv,&tz)) {
674     Tcl_SetResult(interp,"Error occured during call to gettimeofday()",TCL_VOLATILE);
675     return TCL_ERROR;
676   }
677   sprintf(temptime,"%.6f",tv.tv_sec+tv.tv_usec/1000000.0);
678   Tcl_SetResult(interp,temptime,TCL_VOLATILE);
679   return TCL_OK;
680 }
681 
TT_Proc_newserver(TT_PROC_ARGS)682 int TT_Proc_newserver(TT_PROC_ARGS) {
683   tserver *serverp;
684   char *check;
685   char *colon;
686   char *copy;
687   if(argc==1) {
688     serverp=new tserver("",0,"");
689   } else {
690     if(!strlen(argv[1])) {
691       serverp=new tserver("",0,"");
692     } else {
693       switch(argc) {
694       case 2:
695 	if(!(copy=strdup(argv[1]))) {
696 	  fprintf(stderr,M_OUT_OF_MEMORY);
697 	}
698 	if(!(colon=strstr(copy,":"))) {
699 	  // server
700 	  serverp=new tserver(copy,0,"");
701 	} else {
702 	  *colon=0;
703 	  colon++;
704 	  if(!(check=strstr(colon,":"))) {
705 	    // server:port
706 	    serverp=new tserver(copy,atoi(colon),"");
707 	  } else {
708 	    // server::password
709 	    // server:port:password
710 	    *check=0;
711 	    serverp=new tserver(copy,atoi(colon),check+1);
712 	  }
713 	}
714 	free(copy);
715 	break;
716       case 3:
717 	// server port
718 	serverp=new tserver(argv[1],atoi(argv[2]),"");
719 	break;
720       case 4:
721 	// server port password
722 	serverp=new tserver(argv[1],atoi(argv[2]),argv[3]);
723 	break;
724       default:
725 	Tcl_SetResult(interp,"usage: newserver [<server>[:[<port>][:<password>]]]",TCL_STATIC);
726 	return TCL_ERROR;
727       }
728     }
729   }
730   Tcl_SetResult(interp,strnum(serverp->index),TCL_VOLATILE);
731   return TCL_OK;
732 }
733 
TT_Proc_nextwindow(TT_PROC_ARGS)734 int TT_Proc_nextwindow(TT_PROC_ARGS) {
735   twindow window;
736   twindow *windowp;
737 
738   strcpy(window.pathname,currentwindow);
739   if((windowp=windows.find(window))) {
740     if(windowp->index<windows.lastindex()) {
741       TT_EvalF(TT_ARGS,"totop %d",windowp->index+1);
742     } else {
743       TT_Eval(TT_ARGS,"totop 0");
744     }
745   }
746   return TCL_OK;
747 }
748 
TT_Proc_parse(TT_PROC_ARGS)749 int TT_Proc_parse(TT_PROC_ARGS) {
750   if(argc<3) {
751     Tcl_SetResult(interp,"usage: parse <command> <argument> [<argument> ...]",TCL_STATIC);
752     return TCL_ERROR;
753   }
754   if(!strcasecmp(argv[1],"format")) {
755     //parse format TYPE "format string"
756     if(argc!=4) {
757       Tcl_SetResult(interp,"usage: parse format <type> <format_string>",TCL_STATIC);
758       return TCL_ERROR;
759     }
760   } else if(!strcasecmp(argv[1],"args")) {
761     //parse args TYPE "arg types"
762     if(argc!=4) {
763       Tcl_SetResult(interp,"usage: parse args <type> <input_arguments>",TCL_STATIC);
764       return TCL_ERROR;
765     }
766   } else if(!strcasecmp(argv[1],"location")) {
767     //parse location TYPE "location string"
768     //[parse location TYPE]
769     if(argc>4) {
770       Tcl_SetResult(interp,"usage: parse location <type> [<location_string>]",TCL_STATIC);
771       return TCL_ERROR;
772     }
773   } else {
774     //[parse TYPE args ...]
775   }
776   return TCL_OK;
777 }
778 
mystrtok(char * s,char * delim)779 char *mystrtok(char *s, char *delim) {
780   static char *nextposition;
781   char *position;
782   char *oldposition;
783   // DEBUG
784   //TT_EvalF(TT_ARGS,".raw.text insert end \"DEBUG - s is *%d*\\n\"",(int)s);
785   if(s) nextposition=s;
786   // DEBUG
787   //TT_EvalF(TT_ARGS,".raw.text insert end \"DEBUG - nextposition  is *%d*\\n\"",(int)nextposition);
788   if(!nextposition) return NULL;
789   // DEBUG
790   //TT_EvalF(TT_ARGS,".raw.text insert end \"DEBUG - nextposition is non-null and is *%q*\\n\"",nextposition);
791   if((position=strpbrk(nextposition,delim))) {
792     // DEBUG
793     //TT_EvalF(TT_ARGS,".raw.text insert end \"DEBUG - Found a *%q*\\n\"",delim);
794     *position=0;
795     position++;
796   }
797   oldposition=nextposition;
798   // DEBUG
799   //TT_EvalF(TT_ARGS,".raw.text insert end \"DEBUG - Returning *%q*\\n\"",oldposition);
800   nextposition=position;
801   // DEBUG
802   //TT_EvalF(TT_ARGS,".raw.text insert end \"DEBUG - To be checked next time is *%q*\\n\"",nextposition);
803   return oldposition;
804 }
805 
TT_Proc_parseentry(TT_PROC_ARGS)806 int TT_Proc_parseentry(TT_PROC_ARGS) {
807   // Split up long lines!!!!
808   // argv[1] is the origin window
809   tchan chan;
810   tchan *chanp;
811   tquery query;
812   tquery *queryp;
813   char temp[TEMPLEN];
814   char *theentry;
815   char *returned;
816   char *position;
817   twindow window;
818   twindow *windowp;
819   tcommand command;
820 
821   if(argc!=2) {
822     Tcl_SetResult(interp,"Usage: parseentry <pathname>",TCL_STATIC);
823     return TCL_ERROR;
824   }
825   strcpy(window.pathname,argv[1]);
826   if((windowp=windows.find(window))) {
827     theentry=strdup(TT_StrF(TT_ARGS,"%s.entry get",argv[1]));
828     if(!theentry) {
829       fprintf(stderr,M_OUT_OF_MEMORY);
830       exit(1);
831     }
832     TT_EvalF(TT_ARGS,"%s.entry delete 0 end",argv[1]);
833     if(strlen(TT_StrF(TT_ARGS,"info command ::event_enter"))) {
834       returned=strdup(TT_StrF(TT_ARGS,"::event_enter %q %s",theentry,argv[1]));
835       free(theentry);
836       if(!returned) {
837 	fprintf(stderr,M_OUT_OF_MEMORY);
838 	exit(1);
839       }
840       theentry=returned;
841     }
842     if(strlen(theentry)) {
843       if(historycommand) free(historycommand);
844       historycommand=0;
845       historyposition=-1;
846       command.line=strdup(theentry);
847       history.insert_start(command);
848       if(history.lastindex()==COMMANDHISTORYLEN) {
849         command.index=history.lastindex();
850 	history.deleteitem(command);
851       }
852       position=mystrtok(theentry,"\n");
853       while(position) {
854 	if(!strlen(position)) {
855 	  position=mystrtok(0,"\n");
856 	  continue;
857 	}
858 	if(position[0]=='/') {
859 	  do_command(argv[1],position);
860 	} else {
861 	  if(!strncmp(argv[1],".channel",8)) {
862 	    strcpy(chan.pathname,argv[1]);
863 	    if((chanp=windowp->server->chanlist.find(chan))) {
864 	      sprintf(temp,"PRIVMSG %s :%s",chanp->name,position);
865 	      windowp->server->senddata(temp);
866 	    }
867 	  }
868 	  if(!strncmp(argv[1],".query",6)) {
869 	    strcpy(query.pathname,argv[1]);
870 	    if((queryp=windowp->server->querylist.find(query))) {
871 	      sprintf(temp,"PRIVMSG %s :%s",queryp->getname(),position);
872 	      windowp->server->senddata(temp);
873 	    }
874 	  }
875 	  if(!strncmp(argv[1],".chat",5)) {
876 	    twindow window2;
877 	    twindow *windowp2;
878 	    strcpy(window2.pathname,argv[1]);
879 	    if((windowp2=windows.find(window2))) {
880 	      if(windowp2->dcc) {
881 		windowp2->dcc->senddata(position);
882 	      }
883 	    }
884 	  }
885 	  if(strncmp(argv[1],".status",7)&&strcmp(argv[1],".main")) {
886 	    fdisplay("OUTGOING_TEXT",windowp->server->index,2,argv[1],position);
887 	  }
888 	}
889 	position=mystrtok(0,"\n");
890       }
891     }
892     free(theentry);
893   }
894   lastcommand=time(0);
895   return TCL_OK;
896 }
897 
TT_Proc_popup(TT_PROC_ARGS)898 int TT_Proc_popup(TT_PROC_ARGS) {
899   //popup add item <type> <submenu> <title> <command>
900   //popup add submenu <type> <submenu> <title>
901   //popup clear <type> <submenu>
902   //  0     1    2      3         4       5      6
903   char menuname[TEMPLEN];
904   char basemenuname[TEMPLEN];
905   char *position;
906 
907   if(argc<4||argc==5||argc>7) {
908     Tcl_SetResult(interp,"Usage: popup <command> [2 to 5 arguments] (Global)",TCL_VOLATILE);
909     return TCL_ERROR;
910   }
911 
912   if(!strcasecmp(argv[1],"add")&&!strcasecmp(argv[2],"item")) {
913     if(!strncmp(argv[3],"main",4)) {
914       sprintf(menuname,".menu%s%s",argv[3],argv[4]);
915     } else {
916       return TCL_OK;
917     }
918     TT_EvalF(TT_ARGS,"%s add command -label \"%q\" -command %q",menuname,argv[5],argv[6]);
919   }
920 
921   if(!strcasecmp(argv[1],"add")&&!strcasecmp(argv[2],"submenu")) {
922     if(!strncmp(argv[3],"main",4)) {
923       sprintf(menuname,".menu%s%s",argv[3],argv[4]);
924     } else {
925       return TCL_OK;
926     }
927     position=strrchr(menuname,'.');
928     *position=0;
929     strcpy(basemenuname,menuname);
930     *position='.';
931     TT_EvalF(TT_ARGS,"%s add cascade -label \"%q\" -menu \"%q\"",basemenuname,argv[5],menuname);
932     TT_EvalF(TT_ARGS,"menu %s",menuname);
933   }
934 
935   if(!strcasecmp(argv[1],"clear")) {
936     if(!strncmp(argv[2],"main",4)) {
937       sprintf(menuname,".menu%s%s",argv[2],argv[3]);
938     } else {
939       return TCL_OK;
940     }
941     TT_EvalF(TT_ARGS,"destroy %s",menuname);
942     TT_EvalF(TT_ARGS,"menu %s",menuname);
943   }
944 
945   return TCL_OK;
946 }
947 
TT_Proc_previouswindow(TT_PROC_ARGS)948 int TT_Proc_previouswindow(TT_PROC_ARGS) {
949   twindow window;
950   twindow *windowp;
951 
952   strcpy(window.pathname,currentwindow);
953   if((windowp=windows.find(window))) {
954     if(windowp->index>0) {
955       TT_EvalF(TT_ARGS,"totop %d",windowp->index-1);
956     } else {
957       TT_EvalF(TT_ARGS,"totop %d",windows.lastindex());
958     }
959   }
960   return TCL_OK;
961 }
962 
TT_Proc_renamewindow(TT_PROC_ARGS)963 int TT_Proc_renamewindow(TT_PROC_ARGS) {
964   twindow window;
965   twindow *windowp;
966   int oldindex;
967   int newindex;
968   int reallynewindex;
969 
970   if(argc!=3) {
971     Tcl_SetResult(interp,"Usage: renamewindow <pathname> <new name>",TCL_STATIC);
972     return TCL_ERROR;
973   }
974   strcpy(window.pathname,currentwindow);
975   if(!(windowp=windows.find(window))) {
976     fprintf(stderr,"Evil Error: The curent window isn't in the window list.  This should never happen.\n");
977     exit(1);
978   }
979   oldindex=windowp->index;
980   strcpy(window.pathname,argv[1]);
981   if(!(windowp=windows.find(window))) {
982     Tcl_SetResult(interp,"Usage: renamewindow <pathname> <new name> (Invalid pathname specified.)",TCL_STATIC);
983     return TCL_ERROR;
984   }
985   newindex=windowp->index;
986 
987   strcpy(window.pathname,windowp->pathname);
988   window.title=windowp->title;
989   window.server=windowp->server;
990   window.dcc=windowp->dcc;
991 
992   windows.deleteitem(window);
993 
994   strcpy(window.name,argv[2]);
995 
996   reallynewindex=windows.insert_ascending(window);
997 
998   TT_EvalF(TT_ARGS,"QListBox::delete .windowlist %d",newindex);
999 
1000   if(strncmp(".status",argv[1],7)&&strcmp(".main",argv[1])) {
1001     TT_EvalF(TT_ARGS,"QListBox::insert .windowlist %d \"${::dynamic::theme_windowlist_indent}%q\"",reallynewindex,argv[2]);
1002   } else {
1003     TT_EvalF(TT_ARGS,"QListBox::insert .windowlist %d \"%q\"",reallynewindex,argv[2]);
1004   }
1005 
1006   if(oldindex==newindex) {
1007     TT_EvalF(TT_ARGS,"QListBox::select .windowlist %d",reallynewindex);
1008   } else {
1009     // Select old selected window again.
1010     strcpy(window.pathname,currentwindow);
1011     if(!(windowp=windows.find(window))) {
1012       fprintf(stderr,"Evil Error: The curent window isn't in the window list.  This should never happen.\n");
1013       exit(1);
1014     }
1015     TT_EvalF(TT_ARGS,"QListBox::select .windowlist %d",windowp->index);
1016   }
1017   Tcl_SetResult(interp,strnum(reallynewindex),TCL_VOLATILE);
1018   return TCL_OK;
1019 }
1020 
TT_Proc_say(TT_PROC_ARGS)1021 int TT_Proc_say(TT_PROC_ARGS) {
1022   twindow window;
1023   twindow *windowp;
1024   tchan chan;
1025   tchan *chanp;
1026   tquery query;
1027   tquery *queryp;
1028   char argument[TEMPLEN];
1029   char temp[TEMPLEN];
1030   int ok=0;
1031   char *position;
1032   if(argc>3||argc<2) {
1033     Tcl_SetResult(interp,"Usage: say <message> [<target pathname>]",TCL_VOLATILE);
1034     return TCL_ERROR;
1035   }
1036   if(argc==3) {
1037     strcpy(window.pathname,argv[2]);
1038   } else {
1039     strcpy(window.pathname,currentwindow);
1040   }
1041   if(!(windowp=windows.find(window))) {
1042     Tcl_SetResult(interp,"say: Invalid target pathname.",TCL_VOLATILE);
1043     return TCL_ERROR;
1044   }
1045   strcpy(argument,argv[1]);
1046   position=strtok(argument,"\n");
1047   if(!strncmp(window.pathname,".channel",8)) {
1048     strcpy(chan.pathname,window.pathname);
1049     chanp=windowp->server->chanlist.find(chan);
1050     while(position) {
1051       sprintf(temp,"PRIVMSG %s :%s",chanp->name,position);
1052       windowp->server->senddata(temp);
1053       fdisplay("OUTGOING_TEXT",windowp->server->index,2,window.pathname,position);
1054       position=strtok(NULL,"\n");
1055     }
1056     ok=1;
1057   }
1058   if(!strncmp(window.pathname,".query",6)) {
1059     strcpy(query.pathname,window.pathname);
1060     queryp=windowp->server->querylist.find(query);
1061     while(position) {
1062       sprintf(temp,"PRIVMSG %s :%s",queryp->getname(),position);
1063       windowp->server->senddata(temp);
1064       fdisplay("OUTGOING_TEXT",windowp->server->index,2,window.pathname,position);
1065       position=strtok(NULL,"\n");
1066     }
1067     ok=1;
1068   }
1069   if(!strncmp(window.pathname,".chat",5)) {
1070     while(position) {
1071       windowp->dcc->senddata(position);
1072       fdisplay("OUTGOING_TEXT",windowp->server->index,2,window.pathname,position);
1073       position=strtok(NULL,"\n");
1074     }
1075     ok=1;
1076   }
1077   if(ok) return TCL_OK; else {
1078     Tcl_SetResult(interp,"say: Improper say usage.  Please use only for query, channel, or chat windows.",TCL_VOLATILE);
1079     return TCL_ERROR;
1080   }
1081 }
1082 
TT_Proc_selectednicks(TT_PROC_ARGS)1083 int TT_Proc_selectednicks(TT_PROC_ARGS) {
1084   TT_Eval(TT_ARGS,"\
1085     set tempvariable \"\"\n\
1086     if { [string match \".channel*\" [currentwindow]] } {\n\
1087       foreach index [[currentwindow].nicks curselection] {\n\
1088         lappend tempvariable [string trim [join [[currentwindow].nicks get $index $index]] \"+@\"]\n\
1089       }\n\
1090     }\n\
1091   ");
1092   Tcl_SetResult(interp,
1093 		(char *)TT_Str(TT_ARGS,"set tempvariable"),
1094 		TCL_VOLATILE);
1095   return TCL_OK;
1096 }
1097 
TT_Proc_selectedmodenicks(TT_PROC_ARGS)1098 int TT_Proc_selectedmodenicks(TT_PROC_ARGS) {
1099   TT_Eval(TT_ARGS,"\
1100     set tempvariable \"\"\n\
1101     if { [string match \".channel*\" [currentwindow]] } {\n\
1102       foreach index [[currentwindow].nicks curselection] {\n\
1103         lappend tempvariable [join [[currentwindow].nicks get $index $index]]\b\
1104       }\n\
1105     }\n\
1106   ");
1107   Tcl_SetResult(interp,
1108 		(char *)TT_Str(TT_ARGS,"set tempvariable"),
1109 		TCL_VOLATILE);
1110   return TCL_OK;
1111 }
1112 
TT_Proc_serverindex(TT_PROC_ARGS)1113 int TT_Proc_serverindex(TT_PROC_ARGS) {
1114   twindow window;
1115   twindow *windowp;
1116   if(argc!=2) {
1117     Tcl_SetResult(interp,"Usage: serverindex <pathname>",TCL_STATIC);
1118     return TCL_ERROR;
1119   }
1120   strcpy(window.pathname,argv[1]);
1121   Tcl_SetResult(interp,"-1",TCL_VOLATILE);
1122   if((windowp=windows.find(window))) {
1123     if(windowp->server) {
1124       Tcl_SetResult(interp,strnum(windowp->server->index),TCL_VOLATILE);
1125     }
1126   }
1127   return TCL_OK;
1128 }
1129 
TT_Proc_servers(TT_PROC_ARGS)1130 int TT_Proc_servers(TT_PROC_ARGS) {
1131   twindow *windowp;
1132   string servers;
1133   windows.init_trav();
1134   while((windowp=windows.trav())) {
1135     if(!strncmp(windowp->pathname,".status",7)) {
1136       if(servers.length()) servers+=" ";
1137       servers+=strnum(windowp->server->index);
1138     }
1139   }
1140   Tcl_SetResult(interp,(char *)servers.c_str(),TCL_VOLATILE);
1141   return TCL_OK;
1142 }
1143 
TT_Proc_shutdown(TT_PROC_ARGS)1144 int TT_Proc_shutdown(TT_PROC_ARGS) {
1145   twindow *windowp;
1146   char temp[1000];
1147 
1148   if(fparse_result) free(fparse_result);
1149 
1150   // Clean up format/location hashes
1151   hash_destroy(&formats);
1152   hash_destroy(&activate);
1153   hash_destroy(&locations);
1154 
1155   TT_Eval(TT_ARGS,"set ::dynamic::do_rawview 0");
1156   windows.init_trav();
1157   while((windowp=windows.trav())) {
1158     if(!strncmp(windowp->pathname,".status",7)) {
1159       if(windowp->server) {
1160 	if(windowp->server->connected) {
1161 	  //printf("We are here closing sockets.\n");
1162 	  /*
1163 	  struct linger lin;
1164 	  socklen_t linlen=sizeof(lin);
1165 	  getsockopt(windowp->server->sockfd,SOL_SOCKET,SO_LINGER,&lin,&linlen);
1166 	  printf("%d and %d\n",lin.l_onoff,lin.l_linger);
1167 	  */
1168 	  TT_EvalF(TT_ARGS,"set ::%d::intentional_disconnect 1",windowp->server->index);
1169 	  sprintf(temp,"QUIT :%s",TT_Str(TT_ARGS,"set ::dynamic::default_quit"));
1170 	  windowp->server->senddata(temp);
1171 	  /*
1172 	  printf("Pausing for 5 seconds.\n");
1173 	  sleep(10);
1174 	  printf("Done!\n");
1175 	  printf("Shutdown returned: %d\n",shutdown(windowp->server->sockfd,2));
1176 	  printf("Close returned %d\n",close(windowp->server->sockfd));
1177 	  */
1178 	  shutdown(windowp->server->sockfd,1);
1179 	  close(windowp->server->sockfd);
1180 	}
1181 	if(windowp->server->connecting) close(windowp->server->sockfd);
1182 	delete windowp->server;
1183       }
1184     }
1185   }
1186   return TCL_OK;
1187 }
1188 
TT_Proc_title(TT_PROC_OBJS)1189 int TT_Proc_title(TT_PROC_OBJS) {
1190   int len;
1191   char *arg;
1192   twindow window;
1193   twindow *windowp;
1194   Tcl_Obj *objp;
1195 
1196   if(objc>3||objc<2) {
1197     Tcl_SetResult(interp,"Usage: title <pathname> [<text>]",TCL_VOLATILE);
1198     return TCL_ERROR;
1199   }
1200   strcpy(window.pathname,ARGV(1));
1201   if((windowp=windows.find(window))) {
1202     if(objc==2) {
1203       objp=Tcl_NewStringObj((char *)windowp->title.data(),windowp->title.size());
1204       Tcl_SetObjResult(interp,objp);
1205     } else {
1206       arg=Tcl_GetStringFromObj(objv[2],&len);
1207       windowp->title.assign(arg,len);
1208       if(!strcmp(windowp->pathname,currentwindow)) {
1209 	TT_EvalF(TT_ARGS,"wm title . %q",arg);
1210       }
1211     }
1212   } else {
1213     Tcl_SetResult(interp,"Usage: title <pathname> [<text>] (Invalid pathname specified.)",TCL_STATIC);
1214     return TCL_ERROR;
1215   }
1216   return TCL_OK;
1217 }
1218 
TT_Proc_totop(TT_PROC_ARGS)1219 int TT_Proc_totop(TT_PROC_ARGS) {
1220   twindow window;
1221   twindow *windowp;
1222   twindow *windowp2;
1223   string userhostresults;
1224   int n;
1225   int i,i2;
1226   n=atoi(argv[1]);
1227   window.index=n;
1228   windowp=windows.find(window);
1229   if(windowp) {
1230     i=-1;
1231     if(windowp->server) {
1232       i=windowp->server->index;
1233     }
1234     window.index=-1;
1235     strcpy(window.pathname,currentwindow);
1236     if((windowp2=windows.find(window))) {
1237       i2=-1;
1238       if(windowp2->server) {
1239 	i2=windowp2->server->index;
1240       }
1241       TT_EvalF(TT_ARGS," if { [info commands ::event_windowchanged]!=\"\" } { event_windowchanged %q %q %d %d %q %q %d %d }",windowp2->pathname,windowp2->name,i2,windowp2->index,windowp->pathname,windowp->name,i,windowp->index);
1242     }
1243     TT_EvalF(TT_ARGS,"wm title . %q",windowp->title.c_str());
1244   }
1245   if(windowp) {
1246     TT_EvalF(TT_ARGS,"raise %s",windowp->pathname);
1247     TT_EvalF(TT_ARGS,"QListBox::colorize .windowlist %d normal", n);
1248     TT_EvalF(TT_ARGS,"QListBox::select .windowlist %d",n);
1249     TT_EvalF(TT_ARGS,"%s.text see end",windowp->pathname);
1250     TT_EvalF(TT_ARGS,"focus %s.entry",windowp->pathname);
1251     strcpy(currentwindow,windowp->pathname);
1252     if(windowp->server) {
1253       TT_EvalF(TT_ARGS,"::template::condis %d",windowp->server->index);
1254     } else {
1255       TT_Eval(TT_ARGS,"::template::condis -1");
1256     }
1257     TT_Eval(TT_ARGS,"update idletasks");
1258     return TCL_OK;
1259   } else {
1260     return TCL_ERROR;
1261   }
1262 }
1263 
TT_Proc_version(TT_PROC_ARGS)1264 int TT_Proc_version(TT_PROC_ARGS) {
1265   Tcl_SetResult(interp,VERSION,TCL_VOLATILE);
1266   return TCL_OK;
1267 }
1268 
TT_Proc_windowindex(TT_PROC_ARGS)1269 int TT_Proc_windowindex(TT_PROC_ARGS) {
1270   twindow window;
1271   twindow *windowp;
1272   if(argc>2) {
1273     Tcl_SetResult(interp,"Usage: windowindex [<pathname>]",TCL_STATIC);
1274     return TCL_ERROR;
1275   }
1276   if(argc==1) {
1277     strcpy(window.pathname,currentwindow);
1278   } else {
1279     strcpy(window.pathname,argv[1]);
1280   }
1281   Tcl_SetResult(interp,"-1",TCL_STATIC);
1282   if((windowp=windows.find(window))) {
1283     Tcl_SetResult(interp,strnum(windowp->index),TCL_VOLATILE);
1284   } else {
1285     Tcl_SetResult(interp,"Usage: windowindex [<pathname>] (Invalid pathname given.",TCL_STATIC);
1286     return TCL_ERROR;
1287   }
1288   return TCL_OK;
1289 }
1290 
TT_Proc_windowname(TT_PROC_ARGS)1291 int TT_Proc_windowname(TT_PROC_ARGS) {
1292   twindow window;
1293   twindow *windowp;
1294 
1295   if(argc>1) {
1296     strcpy(window.pathname,argv[1]);
1297   } else {
1298     strcpy(window.pathname,currentwindow);
1299   }
1300   if((windowp=windows.find(window))) {
1301     Tcl_SetResult(interp,windowp->name,TCL_VOLATILE);
1302   }
1303   return TCL_OK;
1304 }
1305 
TT_Proc_windows(TT_PROC_ARGS)1306 int TT_Proc_windows(TT_PROC_ARGS) {
1307   Tcl_Obj *listptr;
1308   Tcl_Obj *objptr;
1309   twindow *windowp;
1310   if(argc!=1) {
1311     Tcl_SetResult(interp,"Usage: windows",TCL_STATIC);
1312     return TCL_ERROR;
1313   }
1314   listptr=Tcl_NewListObj(0,0);
1315   windows.init_trav();
1316   while((windowp=windows.trav())) {
1317     objptr=Tcl_NewStringObj(windowp->pathname,strlen(windowp->pathname));
1318     if(Tcl_ListObjAppendElement(interp,listptr,objptr)==TCL_ERROR) return TCL_ERROR;
1319   }
1320   Tcl_SetObjResult(interp,listptr);
1321   return TCL_OK;
1322 }
1323 
TT_Proc_windowtype(TT_PROC_ARGS)1324 int TT_Proc_windowtype(TT_PROC_ARGS) {
1325   int x=1;
1326   char temppath[20];
1327   if(argc!=2) {
1328     Tcl_SetResult(interp,"Usage: windowtype <pathname>",TCL_STATIC);
1329     return TCL_ERROR;
1330   }
1331   strcpy(temppath,argv[1]);
1332   while(isalpha(temppath[x])) x++;
1333   temppath[x]=0;
1334   Tcl_SetResult(interp,temppath+1,TCL_VOLATILE);
1335   return TCL_OK;
1336 }
1337