1 | /* |
---|
2 | Copyright 1991 by the Massachusetts Institute of Technology |
---|
3 | |
---|
4 | Permission to use, copy, modify, and distribute this |
---|
5 | software and its documentation for any purpose and without |
---|
6 | fee is hereby granted, provided that the above copyright |
---|
7 | notice appear in all copies and that both that copyright |
---|
8 | notice and this permission notice appear in supporting |
---|
9 | documentation, and that the name of M.I.T. not be used in |
---|
10 | advertising or publicity pertaining to distribution of the |
---|
11 | software without specific, written prior permission. |
---|
12 | M.I.T. makes no representations about the suitability of |
---|
13 | this software for any purpose. It is provided "as is" |
---|
14 | without express or implied warranty. |
---|
15 | */ |
---|
16 | |
---|
17 | #ifdef POSIX |
---|
18 | #include <unistd.h> |
---|
19 | #endif |
---|
20 | #include <stdio.h> |
---|
21 | #include <string.h> |
---|
22 | #include <fcntl.h> |
---|
23 | |
---|
24 | #include <X11/IntrinsicP.h> |
---|
25 | #include <X11/StringDefs.h> |
---|
26 | #include <X11/CoreP.h> |
---|
27 | |
---|
28 | #include <X11/Xaw/MenuButton.h> |
---|
29 | #include <X11/Xaw/SimpleMenu.h> |
---|
30 | #include <X11/Xaw/Sme.h> |
---|
31 | #include <X11/Xaw/SmeBSB.h> |
---|
32 | #include <X11/Xaw/Cardinals.h> |
---|
33 | |
---|
34 | #include <X11/Xaw/List.h> |
---|
35 | #include <X11/Xaw/SimpleMenP.h> |
---|
36 | #include <X11/Xaw/Paned.h> |
---|
37 | #include <X11/Xaw/Command.h> |
---|
38 | #include <X11/Xaw/Box.h> |
---|
39 | #include <X11/Xaw/AsciiText.h> |
---|
40 | #include <X11/Xaw/TextP.h> |
---|
41 | #include <X11/Xaw/TextSinkP.h> |
---|
42 | #include <X11/Xaw/Dialog.h> |
---|
43 | #include <X11/Xaw/Form.h> |
---|
44 | #include <X11/Xaw/Label.h> |
---|
45 | |
---|
46 | #include "xdsc.h" |
---|
47 | #ifdef sgi |
---|
48 | #define vfork fork |
---|
49 | #endif |
---|
50 | static char rcsid[] = ""; |
---|
51 | |
---|
52 | /* |
---|
53 | ** Globals |
---|
54 | */ |
---|
55 | |
---|
56 | char *RunCommand(); |
---|
57 | TextWidget toptextW, bottextW; |
---|
58 | Boolean debug = False; |
---|
59 | char filebase[50]; |
---|
60 | int topscreen = MAIN; |
---|
61 | Widget topW, paneW; |
---|
62 | void RemoveLetterC(); |
---|
63 | int char_width; |
---|
64 | char axis[10]; |
---|
65 | void TopSelect(), BotSelect(); |
---|
66 | void Update(), Stub(); |
---|
67 | void PrintEvent(); |
---|
68 | int simplemode = 0; |
---|
69 | int edscversion; |
---|
70 | Boolean nocache; |
---|
71 | |
---|
72 | /* |
---|
73 | ** External functions |
---|
74 | */ |
---|
75 | |
---|
76 | extern void PutUpHelp(); |
---|
77 | extern void SubmitTransaction(); |
---|
78 | extern void WriteTransaction(); |
---|
79 | extern char *tempnam(); |
---|
80 | extern int PopdownCB(); |
---|
81 | extern char *getenv(); |
---|
82 | extern void TriggerAdd(), TriggerNum(), TriggerDelete(); |
---|
83 | extern void TriggerWrite(), TriggerPopdown(), TriggerSend(); |
---|
84 | extern void TriggerFocusMove(); |
---|
85 | extern void DispatchClick(); |
---|
86 | extern void FetchIfNecessary(); |
---|
87 | extern int HighlightedTransaction(); |
---|
88 | |
---|
89 | /* |
---|
90 | ** Private functions |
---|
91 | */ |
---|
92 | |
---|
93 | static void MenuCallback(); |
---|
94 | static void KeyCallback(); |
---|
95 | static void QuitCB(), HelpCB(); |
---|
96 | static void BuildUserInterface(); |
---|
97 | static void DoTheRightThing(); |
---|
98 | static void DoTheRightThingInReverse(); |
---|
99 | static void CheckEdscVersion(); |
---|
100 | static void BuildSkeleton(); |
---|
101 | static unsigned long GetFontWidth(); |
---|
102 | |
---|
103 | /* |
---|
104 | ** Private globals |
---|
105 | */ |
---|
106 | |
---|
107 | static int filedesparent[2], filedeschild[2]; |
---|
108 | static FILE *inputfile, *outputfile; |
---|
109 | static char *meetinglist; |
---|
110 | |
---|
111 | static Widget topboxW, botboxW; |
---|
112 | static Widget label1W; |
---|
113 | static int prevfirst = 0; |
---|
114 | static XawTextPosition startOfCurrentMeeting = -1; |
---|
115 | Display *dpy; |
---|
116 | Window root_window; |
---|
117 | static XawTextPosition oldarrow = -1; |
---|
118 | |
---|
119 | /* |
---|
120 | ** Data for top row of buttons |
---|
121 | */ |
---|
122 | |
---|
123 | static char * menu_labels0[MAX_BUTTONS] = { |
---|
124 | "Down", "Up", "update", "configure", "mode", |
---|
125 | "show", "HELP", "QUIT"}; |
---|
126 | |
---|
127 | static char * menu_names0[MAX_BUTTONS] = { |
---|
128 | "downbutton", "upbutton", "updatebutton", "configurebutton", |
---|
129 | "modebutton", "showbutton", "helpbutton", "quitbutton"}; |
---|
130 | |
---|
131 | static char * submenu_labels0[MAX_BUTTONS][MAX_MENU_LEN] = { |
---|
132 | { NULL, NULL, NULL, NULL }, |
---|
133 | { NULL, NULL, NULL, NULL }, |
---|
134 | { NULL, NULL, NULL, NULL }, |
---|
135 | { "add meeting", "delete meeting", NULL, NULL }, |
---|
136 | { "transactions", "meetings", NULL, NULL }, |
---|
137 | { "unread", "all", "back ten", NULL }, |
---|
138 | { NULL, NULL, NULL, NULL }, |
---|
139 | { NULL, NULL, NULL, NULL }}; |
---|
140 | |
---|
141 | static char * submenu_names0[MAX_BUTTONS][MAX_MENU_LEN] = { |
---|
142 | { NULL, NULL, NULL, NULL }, |
---|
143 | { NULL, NULL, NULL, NULL }, |
---|
144 | { NULL, NULL, NULL, NULL }, |
---|
145 | { "addbutton", "deletebutton", NULL, NULL }, |
---|
146 | { "transbutton", "meetingbutton", NULL, NULL }, |
---|
147 | { "unreadbutton", "allbutton", "backbutton", NULL }, |
---|
148 | { NULL, NULL, NULL, NULL }, |
---|
149 | { NULL, NULL, NULL, NULL }}; |
---|
150 | |
---|
151 | /* |
---|
152 | ** Data for bottom row of buttons |
---|
153 | */ |
---|
154 | |
---|
155 | static char * menu_labels1[MAX_BUTTONS] = { |
---|
156 | "next", "prev", "Next in chain", "Prev in chain", |
---|
157 | "goto", "enter", "write", NULL }; |
---|
158 | |
---|
159 | static char * menu_names1[MAX_BUTTONS] = { |
---|
160 | "nextbutton", "prevbutton", "nchainbutton", "pchainbutton", |
---|
161 | "gotobutton", "enterbutton", "writebutton", NULL }; |
---|
162 | |
---|
163 | static char * submenu_labels1[MAX_BUTTONS][MAX_MENU_LEN] = { |
---|
164 | { NULL, NULL, NULL, NULL }, |
---|
165 | { NULL, NULL, NULL, NULL }, |
---|
166 | { NULL, NULL, NULL, NULL }, |
---|
167 | { NULL, NULL, NULL, NULL }, |
---|
168 | { "number", "first", "last", "start of chain", "end of chain", NULL }, |
---|
169 | { "reply", "new transaction", NULL }, |
---|
170 | { "write to file", "mail to someone", NULL }}; |
---|
171 | |
---|
172 | static char * submenu_names1[MAX_BUTTONS][MAX_MENU_LEN] = { |
---|
173 | { NULL, NULL, NULL, NULL }, |
---|
174 | { NULL, NULL, NULL, NULL }, |
---|
175 | { NULL, NULL, NULL, NULL }, |
---|
176 | { NULL, NULL, NULL, NULL }, |
---|
177 | { "numberbutton", "firstbutton", "lastbutton", "frefbutton", "lrefbutton",NULL }, |
---|
178 | { "replybutton", "newbutton", NULL }, |
---|
179 | { "writebutton", "mailbutton", NULL }}; |
---|
180 | |
---|
181 | #if 0 |
---|
182 | typedef struct{ |
---|
183 | Boolean logging_on; |
---|
184 | String log_file; |
---|
185 | } defaults; |
---|
186 | |
---|
187 | static defaults defs; |
---|
188 | |
---|
189 | static XtResource app_resources[] = { |
---|
190 | { "loggingOn", "LoggingOn", |
---|
191 | XtRBoolean, sizeof (Boolean), XtOffset (defaults *, logging_on), |
---|
192 | XtRString, "true" }, |
---|
193 | { "logfile", "Logfile", |
---|
194 | XtRString, sizeof (String), XtOffset (defaults *, log_file), |
---|
195 | XtRString, "/afs/athena.mit.edu/user/s/sao/scores/xdsc.log"}, |
---|
196 | }; |
---|
197 | #endif |
---|
198 | |
---|
199 | |
---|
200 | EntryRec toplevelbuttons[2][MAX_BUTTONS]; |
---|
201 | |
---|
202 | void |
---|
203 | main(argc, argv) |
---|
204 | int argc; |
---|
205 | char *argv[]; |
---|
206 | { |
---|
207 | int pid; |
---|
208 | char *oldpath, *newpath, *myname; |
---|
209 | Arg args[1]; |
---|
210 | int width; |
---|
211 | char commandline[100]; |
---|
212 | |
---|
213 | if (argc > 1 && !strcmp(argv[1], "-debug")) |
---|
214 | debug = True; |
---|
215 | |
---|
216 | myname = (myname = strrchr(argv[0], '/')) ? myname + 1 : argv[0]; |
---|
217 | |
---|
218 | if (!strcmp (myname, "lucy")) |
---|
219 | simplemode = True; |
---|
220 | else |
---|
221 | simplemode = False; |
---|
222 | |
---|
223 | if (simplemode) { |
---|
224 | topW = XtInitialize("topwidget", "Lucy", NULL, 0, &argc, argv); |
---|
225 | } |
---|
226 | else |
---|
227 | topW = XtInitialize("topwidget", "Xdsc", NULL, 0, &argc, argv); |
---|
228 | |
---|
229 | BuildSkeleton(); |
---|
230 | |
---|
231 | /* |
---|
232 | ** Set our width to 80 chars wide in the current font. Min value of 500 |
---|
233 | ** means that all the lower buttons will fit. |
---|
234 | |
---|
235 | original code |
---|
236 | char_width = (((TextSinkObject) (toptextW->text.sink))-> |
---|
237 | text_sink.font->max_bounds.width); |
---|
238 | |
---|
239 | removed because font parameter is either private or nonexistent (private in |
---|
240 | mit Xaw include files, nonexistent in others). |
---|
241 | |
---|
242 | borrowed code from Xaw/TextSink.c to write a generic GetFontWidth routine. |
---|
243 | rearranged some to use font resource, rather than accessing internals. |
---|
244 | |
---|
245 | mdb 7/26/96 |
---|
246 | |
---|
247 | */ |
---|
248 | |
---|
249 | char_width = (int)GetFontWidth(toptextW); |
---|
250 | width = 80 * char_width; |
---|
251 | XtSetArg(args[0], XtNwidth, width < 500 ? 500 : width); |
---|
252 | XtSetValues(topW, args, 1); |
---|
253 | |
---|
254 | /* |
---|
255 | XtRealizeWidget(topW); |
---|
256 | XSync(XtDisplay(topW), False); |
---|
257 | */ |
---|
258 | |
---|
259 | if (debug) |
---|
260 | fprintf (stderr, "Debugging is on\n"); |
---|
261 | |
---|
262 | sprintf (filebase,"/usr/tmp/xdsc%d",getpid()); |
---|
263 | |
---|
264 | if (debug) |
---|
265 | fprintf (stderr, "filebase is %s\n", filebase); |
---|
266 | |
---|
267 | pipe (filedesparent); |
---|
268 | pipe (filedeschild); |
---|
269 | |
---|
270 | pid = vfork(); |
---|
271 | |
---|
272 | if (pid == 0) |
---|
273 | SetUpEdsc(); |
---|
274 | |
---|
275 | close (filedesparent[1]); |
---|
276 | close (filedeschild[0]); |
---|
277 | |
---|
278 | inputfile = fdopen (filedesparent[0], "r"); |
---|
279 | outputfile = fdopen (filedeschild[1], "w"); |
---|
280 | |
---|
281 | CheckEdscVersion(); |
---|
282 | ParseMeetingsFile(); |
---|
283 | |
---|
284 | oldpath = getenv("XFILESEARCHPATH"); |
---|
285 | |
---|
286 | |
---|
287 | |
---|
288 | #define AppdefaultsInStafftools 0 |
---|
289 | |
---|
290 | #if AppdefaultsInStafftools |
---|
291 | #if defined(mips) || defined(_AIX) |
---|
292 | if (!oldpath) { |
---|
293 | newpath = (char *) malloc (100); |
---|
294 | strcpy (newpath, "XFILESEARCHPATH=/mit/StaffTools/lib/X11/app-defaults/%N"); |
---|
295 | } |
---|
296 | else { |
---|
297 | newpath = (char *) malloc (100 + strlen (oldpath)); |
---|
298 | sprintf (newpath, "XFILESEARCHPATH=%s:/mit/StaffTools/lib/X11/app-defaults/%%N",oldpath); |
---|
299 | } |
---|
300 | putenv (newpath); |
---|
301 | #else |
---|
302 | if (!oldpath) { |
---|
303 | newpath = (char *) malloc (50); |
---|
304 | strcpy (newpath, "/mit/StaffTools/lib/X11/app-defaults/%N"); |
---|
305 | } |
---|
306 | else { |
---|
307 | newpath = (char *) malloc (50 + strlen (oldpath)); |
---|
308 | sprintf (newpath, "%s:/mit/StaffTools/lib/X11/app-defaults/%%N",oldpath); |
---|
309 | } |
---|
310 | setenv ("XFILESEARCHPATH",newpath,1); |
---|
311 | |
---|
312 | #endif |
---|
313 | myfree (newpath); |
---|
314 | #endif |
---|
315 | |
---|
316 | #if 0 |
---|
317 | XtGetApplicationResources( topW, (XtPointer) &defs, |
---|
318 | app_resources, XtNumber (app_resources), |
---|
319 | NULL, 0); |
---|
320 | |
---|
321 | if (defs.logging_on) { |
---|
322 | sprintf (commandline, "machtype >> %s", defs.log_file); |
---|
323 | system (commandline); |
---|
324 | |
---|
325 | sprintf (commandline, "date >> %s", defs.log_file); |
---|
326 | system (commandline); |
---|
327 | } |
---|
328 | #endif |
---|
329 | |
---|
330 | |
---|
331 | BuildUserInterface(); |
---|
332 | XtRealizeWidget(topW); |
---|
333 | |
---|
334 | dpy = XtDisplay(topW); |
---|
335 | root_window = XtWindow(topW); |
---|
336 | |
---|
337 | (void) MoveToMeeting(INITIALIZE); |
---|
338 | /* |
---|
339 | ** If running in simplemode, switch to reading transactions and put up |
---|
340 | ** the list of unread ones. |
---|
341 | */ |
---|
342 | if (simplemode) { |
---|
343 | TopSelect (NULL, 4, NULL); |
---|
344 | BotSelect (NULL, 0, NULL); |
---|
345 | } |
---|
346 | CheckButtonSensitivity(BUTTONS_UPDATE); |
---|
347 | XtMainLoop(); |
---|
348 | } |
---|
349 | |
---|
350 | SetUpEdsc() |
---|
351 | { |
---|
352 | int retval; |
---|
353 | char commandtorun[50]; |
---|
354 | char machtype[20]; |
---|
355 | char *envcommand; |
---|
356 | |
---|
357 | envcommand = getenv("EDSC"); |
---|
358 | strcpy (commandtorun, envcommand ? envcommand : EDSC_PATH); |
---|
359 | |
---|
360 | close (filedesparent[0]); |
---|
361 | close (filedeschild[1]); |
---|
362 | |
---|
363 | dup2 (filedeschild[0], 0); |
---|
364 | dup2 (filedesparent[1], 1); |
---|
365 | |
---|
366 | if (debug) |
---|
367 | fprintf (stderr,"commandtorun = '%s'\n", commandtorun); |
---|
368 | |
---|
369 | retval = execlp (commandtorun, commandtorun, 0); |
---|
370 | |
---|
371 | fprintf (stderr, "Fatal error: Unable to exec '%s'\n",commandtorun); |
---|
372 | _exit (-1); |
---|
373 | } |
---|
374 | |
---|
375 | /* |
---|
376 | ** Put up enough of the application that the user doesn't think it's hung... |
---|
377 | */ |
---|
378 | |
---|
379 | static void |
---|
380 | BuildSkeleton() |
---|
381 | { |
---|
382 | Arg args[5]; |
---|
383 | unsigned int n; |
---|
384 | static XtActionsRec actions[] = { |
---|
385 | {"FetchIfNecessary", FetchIfNecessary}, |
---|
386 | {"MenuCallback", MenuCallback}, |
---|
387 | {"KeyCallback", KeyCallback}, |
---|
388 | {"Update", Update}, |
---|
389 | {"DispatchClick", DispatchClick}, |
---|
390 | {"TriggerAdd", TriggerAdd}, |
---|
391 | {"TriggerDelete", TriggerDelete}, |
---|
392 | {"TriggerFocusMove", TriggerFocusMove}, |
---|
393 | {"TriggerNum", TriggerNum}, |
---|
394 | {"TriggerPopdown", TriggerPopdown}, |
---|
395 | {"TriggerSend", TriggerSend}, |
---|
396 | {"TriggerWrite", TriggerWrite}, |
---|
397 | {"DoTheRightThing", DoTheRightThing}, |
---|
398 | {"DoTheRightThingInReverse", DoTheRightThingInReverse}, |
---|
399 | {"HelpCB", HelpCB}, |
---|
400 | {"QuitCB", QuitCB}, |
---|
401 | {"PopdownCB", (XtActionProc) PopdownCB}, |
---|
402 | {"Stub", Stub}, |
---|
403 | {"PrintEvent", PrintEvent}}; |
---|
404 | |
---|
405 | |
---|
406 | n = 0; |
---|
407 | paneW = XtCreateManagedWidget( |
---|
408 | "pane", |
---|
409 | panedWidgetClass, |
---|
410 | topW, |
---|
411 | args, |
---|
412 | n); |
---|
413 | |
---|
414 | n = 0; |
---|
415 | topboxW = XtCreateManagedWidget( |
---|
416 | "topbox", |
---|
417 | boxWidgetClass, |
---|
418 | paneW, |
---|
419 | args, |
---|
420 | n); |
---|
421 | |
---|
422 | XtAppAddActions ( XtWidgetToApplicationContext(topboxW), |
---|
423 | actions, XtNumber(actions)); |
---|
424 | |
---|
425 | XawSimpleMenuAddGlobalActions(XtWidgetToApplicationContext(topboxW)); |
---|
426 | |
---|
427 | AddChildren (topboxW, 0); |
---|
428 | |
---|
429 | n = 0; |
---|
430 | XtSetArg(args[n], XtNstring, "Please wait..."); n++; |
---|
431 | XtSetArg(args[n], XtNeditType, XawtextEdit); n++; |
---|
432 | XtSetArg(args[n], XtNuseStringInPlace, False); n++; |
---|
433 | |
---|
434 | toptextW = (TextWidget) XtCreateManagedWidget( |
---|
435 | "toptext", |
---|
436 | asciiTextWidgetClass, |
---|
437 | paneW, |
---|
438 | args, |
---|
439 | n); |
---|
440 | |
---|
441 | n = 0; |
---|
442 | XtSetArg(args[n], XtNeditType, XawtextRead); n++; |
---|
443 | label1W = XtCreateManagedWidget( |
---|
444 | "label", |
---|
445 | asciiTextWidgetClass, |
---|
446 | paneW, |
---|
447 | args, |
---|
448 | n); |
---|
449 | |
---|
450 | n = 0; |
---|
451 | botboxW = XtCreateWidget( |
---|
452 | "botbox", |
---|
453 | boxWidgetClass, |
---|
454 | paneW, |
---|
455 | args, |
---|
456 | n); |
---|
457 | |
---|
458 | AddChildren (botboxW, 1); |
---|
459 | |
---|
460 | if (!simplemode) |
---|
461 | XtManageChild (botboxW); |
---|
462 | |
---|
463 | n = 0; |
---|
464 | XtSetArg(args[n], XtNeditType, XawtextRead); n++; |
---|
465 | bottextW = (TextWidget) XtCreateManagedWidget( |
---|
466 | "bottext", |
---|
467 | asciiTextWidgetClass, |
---|
468 | paneW, |
---|
469 | args, |
---|
470 | n); |
---|
471 | } |
---|
472 | |
---|
473 | static void |
---|
474 | BuildUserInterface() |
---|
475 | { |
---|
476 | Arg args[5]; |
---|
477 | unsigned int n; |
---|
478 | Dimension foo; |
---|
479 | |
---|
480 | static XtActionsRec actions[] = { |
---|
481 | {"FetchIfNecessary", FetchIfNecessary}, |
---|
482 | {"MenuCallback", MenuCallback}, |
---|
483 | {"KeyCallback", KeyCallback}, |
---|
484 | {"Update", Update}, |
---|
485 | {"DispatchClick", DispatchClick}, |
---|
486 | {"TriggerAdd", TriggerAdd}, |
---|
487 | {"TriggerDelete", TriggerDelete}, |
---|
488 | {"TriggerFocusMove", TriggerFocusMove}, |
---|
489 | {"TriggerNum", TriggerNum}, |
---|
490 | {"TriggerPopdown", TriggerPopdown}, |
---|
491 | {"TriggerSend", TriggerSend}, |
---|
492 | {"TriggerWrite", TriggerWrite}, |
---|
493 | {"DoTheRightThing", DoTheRightThing}, |
---|
494 | {"DoTheRightThingInReverse", DoTheRightThingInReverse}, |
---|
495 | {"HelpCB", HelpCB}, |
---|
496 | {"QuitCB", QuitCB}, |
---|
497 | {"PopdownCB", (XtActionProc) PopdownCB}, |
---|
498 | {"Stub", Stub}, |
---|
499 | {"PrintEvent", PrintEvent}}; |
---|
500 | |
---|
501 | /* |
---|
502 | n = 0; |
---|
503 | paneW = XtCreateManagedWidget( |
---|
504 | "pane", |
---|
505 | panedWidgetClass, |
---|
506 | topW, |
---|
507 | args, |
---|
508 | n); |
---|
509 | |
---|
510 | |
---|
511 | n = 0; |
---|
512 | topboxW = XtCreateManagedWidget( |
---|
513 | "topbox", |
---|
514 | boxWidgetClass, |
---|
515 | paneW, |
---|
516 | args, |
---|
517 | n); |
---|
518 | |
---|
519 | XtAppAddActions ( XtWidgetToApplicationContext(topboxW), |
---|
520 | actions, XtNumber(actions)); |
---|
521 | |
---|
522 | XawSimpleMenuAddGlobalActions(XtWidgetToApplicationContext(topboxW)); |
---|
523 | |
---|
524 | AddChildren (topboxW, 0); |
---|
525 | */ |
---|
526 | |
---|
527 | n = 0; |
---|
528 | XtSetArg(args[n], XtNstring, meetinglist); n++; |
---|
529 | XtSetValues(toptextW, args, n); |
---|
530 | |
---|
531 | /* |
---|
532 | n = 0; |
---|
533 | XtSetArg(args[n], XtNstring, meetinglist); n++; |
---|
534 | XtSetArg(args[n], XtNeditType, XawtextEdit); n++; |
---|
535 | XtSetArg(args[n], XtNuseStringInPlace, False); n++; |
---|
536 | |
---|
537 | toptextW = (TextWidget) XtCreateManagedWidget( |
---|
538 | "toptext", |
---|
539 | asciiTextWidgetClass, |
---|
540 | paneW, |
---|
541 | args, |
---|
542 | n); |
---|
543 | */ |
---|
544 | |
---|
545 | /* |
---|
546 | n = 0; |
---|
547 | XtSetArg(args[n], XtNeditType, XawtextRead); n++; |
---|
548 | label1W = XtCreateManagedWidget( |
---|
549 | "label", |
---|
550 | asciiTextWidgetClass, |
---|
551 | paneW, |
---|
552 | args, |
---|
553 | n); |
---|
554 | |
---|
555 | n = 0; |
---|
556 | botboxW = XtCreateWidget( |
---|
557 | "botbox", |
---|
558 | boxWidgetClass, |
---|
559 | paneW, |
---|
560 | args, |
---|
561 | n); |
---|
562 | |
---|
563 | AddChildren (botboxW, 1); |
---|
564 | |
---|
565 | if (!simplemode) { |
---|
566 | XtManageChild (botboxW); |
---|
567 | } |
---|
568 | |
---|
569 | n = 0; |
---|
570 | XtSetArg(args[n], XtNeditType, XawtextRead); n++; |
---|
571 | bottextW = (TextWidget) XtCreateManagedWidget( |
---|
572 | "bottext", |
---|
573 | asciiTextWidgetClass, |
---|
574 | paneW, |
---|
575 | args, |
---|
576 | n); |
---|
577 | */ |
---|
578 | |
---|
579 | /* |
---|
580 | ** Add the pane's accelerators to the text widgets and the other kids. |
---|
581 | */ |
---|
582 | XtInstallAccelerators(toptextW, paneW); |
---|
583 | XtInstallAccelerators(bottextW, paneW); |
---|
584 | XtInstallAllAccelerators(paneW, paneW); |
---|
585 | |
---|
586 | } |
---|
587 | |
---|
588 | /* |
---|
589 | ** MenuCallback is called for key hits on menu entries. |
---|
590 | ** It gets two parameters: First, the number of the menubutton |
---|
591 | ** secondly, the index of the entry in the menu. It |
---|
592 | ** packs the two parameters into an int and manually calls TopSelect(). |
---|
593 | */ |
---|
594 | |
---|
595 | static void |
---|
596 | MenuCallback(w, event, params, num_params) |
---|
597 | Widget w; |
---|
598 | XEvent *event; |
---|
599 | String *params; |
---|
600 | int *num_params; |
---|
601 | { |
---|
602 | int buttonnum, entrynum; |
---|
603 | int whichrow; |
---|
604 | |
---|
605 | if (*num_params != 2) |
---|
606 | goto ABORT; |
---|
607 | |
---|
608 | for (buttonnum = 0; buttonnum < MAX_BUTTONS; buttonnum++) { |
---|
609 | if ( menu_names0[buttonnum] && |
---|
610 | !strcmp(menu_names0[buttonnum], params[0])) { |
---|
611 | whichrow = 0; |
---|
612 | break; |
---|
613 | } |
---|
614 | if ( menu_names1[buttonnum] && |
---|
615 | !strcmp(menu_names1[buttonnum], params[0])) { |
---|
616 | whichrow = 1; |
---|
617 | break; |
---|
618 | } |
---|
619 | } |
---|
620 | |
---|
621 | if (buttonnum == MAX_BUTTONS) |
---|
622 | goto ABORT; |
---|
623 | |
---|
624 | for (entrynum = 0; entrynum < MAX_MENU_LEN; entrynum++) { |
---|
625 | if (whichrow == 0) { |
---|
626 | if ( submenu_names0[buttonnum][entrynum] && |
---|
627 | !strcmp(submenu_names0[buttonnum][entrynum], |
---|
628 | params[1])) |
---|
629 | break; |
---|
630 | } |
---|
631 | else { |
---|
632 | if ( submenu_names1[buttonnum][entrynum] && |
---|
633 | !strcmp(submenu_names1[buttonnum][entrynum], |
---|
634 | params[1])) |
---|
635 | break; |
---|
636 | } |
---|
637 | } |
---|
638 | |
---|
639 | if (entrynum == MAX_MENU_LEN) |
---|
640 | goto ABORT; |
---|
641 | |
---|
642 | /* |
---|
643 | ** If a menu item was selected, popdown the menu and relinquish keyboard focus. |
---|
644 | */ |
---|
645 | if (whichrow == 0) |
---|
646 | TopSelect (NULL, buttonnum + (entrynum << 4)); |
---|
647 | else |
---|
648 | BotSelect (NULL, buttonnum + (entrynum << 4)); |
---|
649 | |
---|
650 | if (XtIsSubclass (w, simpleMenuWidgetClass)) |
---|
651 | XtPopdown(w); |
---|
652 | XtSetKeyboardFocus(topW, paneW); |
---|
653 | return; |
---|
654 | |
---|
655 | ABORT: |
---|
656 | |
---|
657 | if (XtIsSubclass (w, simpleMenuWidgetClass)) |
---|
658 | XtPopdown(w); |
---|
659 | XtSetKeyboardFocus(topW, paneW); |
---|
660 | } |
---|
661 | |
---|
662 | /* |
---|
663 | ** TopSelect is called either automatically through the select callback |
---|
664 | ** on a button, or manually through TopCallback when triggered by a |
---|
665 | ** key hit. |
---|
666 | */ |
---|
667 | |
---|
668 | void |
---|
669 | TopSelect(w, client_data, call_data) |
---|
670 | Widget w; /*IGNORED*/ |
---|
671 | XtPointer client_data; |
---|
672 | XtPointer call_data; |
---|
673 | { |
---|
674 | int buttonnum, entrynum; |
---|
675 | Arg args[5]; |
---|
676 | unsigned int n; |
---|
677 | |
---|
678 | entrynum = ((int) client_data) >> 4; |
---|
679 | buttonnum = ((int) client_data) & 0x0F; |
---|
680 | |
---|
681 | switch (buttonnum) { |
---|
682 | /* |
---|
683 | ** Move to next or previous meeting if topscreen is showing meetings, |
---|
684 | ** to next or previous transaction otherwise |
---|
685 | */ |
---|
686 | case 0: |
---|
687 | if (topscreen == MAIN) { |
---|
688 | (void) MoveToMeeting(NEXTNEWS); |
---|
689 | } |
---|
690 | else { |
---|
691 | BotSelect (NULL, 0, NULL); |
---|
692 | } |
---|
693 | break; |
---|
694 | |
---|
695 | case 1: |
---|
696 | if (topscreen == MAIN) { |
---|
697 | (void) MoveToMeeting(PREVNEWS); |
---|
698 | } |
---|
699 | else { |
---|
700 | BotSelect (NULL, 1, NULL); |
---|
701 | } |
---|
702 | break; |
---|
703 | /* |
---|
704 | ** Check for changed meetings |
---|
705 | */ |
---|
706 | case 2: |
---|
707 | MarkLastRead(); |
---|
708 | PutUpTempMessage("Rereading meeting list..."); |
---|
709 | ParseMeetingsFile(); |
---|
710 | n = 0; |
---|
711 | XtSetArg(args[n], XtNstring, meetinglist); n++; |
---|
712 | XtSetValues(toptextW, args, n); |
---|
713 | TakeDownTempMessage(); |
---|
714 | InvalidateHeaders(); |
---|
715 | MoveToMeeting(INITIALIZE); |
---|
716 | break; |
---|
717 | |
---|
718 | /* |
---|
719 | ** configure |
---|
720 | */ |
---|
721 | case 3: |
---|
722 | switch (entrynum) { |
---|
723 | case 0: |
---|
724 | AddMeeting(); |
---|
725 | break; |
---|
726 | case 1: |
---|
727 | DeleteMeeting(); |
---|
728 | break; |
---|
729 | } |
---|
730 | break; |
---|
731 | |
---|
732 | /* |
---|
733 | ** mode |
---|
734 | */ |
---|
735 | case 4: |
---|
736 | switch (entrynum) { |
---|
737 | case 0: |
---|
738 | /* |
---|
739 | ** Put up list of transactions within the current meeting |
---|
740 | */ |
---|
741 | prevfirst = TransactionNum(CURRENT); |
---|
742 | PutUpTransactionList( TransactionNum(CURRENT), |
---|
743 | TransactionNum(LAST)); |
---|
744 | topscreen = LISTTRNS; |
---|
745 | UpdateHighlightedTransaction(TransactionNum(CURRENT),True); |
---|
746 | break; |
---|
747 | case 1: |
---|
748 | /* |
---|
749 | ** Put up list of meetings |
---|
750 | */ |
---|
751 | topscreen = MAIN; |
---|
752 | RestoreTopTextWidget(); |
---|
753 | if ( TransactionNum(HIGHESTSEEN) == |
---|
754 | TransactionNum(LAST)) |
---|
755 | RemoveLetterC(); |
---|
756 | break; |
---|
757 | } |
---|
758 | break; |
---|
759 | |
---|
760 | /* |
---|
761 | ** show |
---|
762 | */ |
---|
763 | case 5: |
---|
764 | if (topscreen != LISTTRNS) |
---|
765 | break; |
---|
766 | switch (entrynum) { |
---|
767 | case 0: |
---|
768 | PutUpTransactionList( |
---|
769 | TransactionNum(HIGHESTSEEN), TransactionNum(LAST)); |
---|
770 | prevfirst = TransactionNum(HIGHESTSEEN); |
---|
771 | UpdateHighlightedTransaction(TransactionNum(CURRENT),True); |
---|
772 | break; |
---|
773 | case 1: |
---|
774 | PutUpTransactionList( |
---|
775 | TransactionNum(FIRST), TransactionNum(LAST)); |
---|
776 | prevfirst = TransactionNum(FIRST); |
---|
777 | UpdateHighlightedTransaction(TransactionNum(CURRENT),True); |
---|
778 | break; |
---|
779 | case 2: |
---|
780 | PutUpTransactionList( prevfirst <= 10 ? 1 : prevfirst - 10, |
---|
781 | TransactionNum(LAST)); |
---|
782 | UpdateHighlightedTransaction(prevfirst - 1,True); |
---|
783 | |
---|
784 | prevfirst -= 10; |
---|
785 | if (prevfirst <=0) prevfirst = 1; |
---|
786 | break; |
---|
787 | } |
---|
788 | break; |
---|
789 | |
---|
790 | case 6: |
---|
791 | PutUpHelp(); |
---|
792 | break; |
---|
793 | case 7: |
---|
794 | QuitCB (NULL, NULL, NULL); |
---|
795 | break; |
---|
796 | } |
---|
797 | } |
---|
798 | |
---|
799 | static void |
---|
800 | BotSelect(w, client_data, call_data) |
---|
801 | Widget w; /*IGNORED*/ |
---|
802 | XtPointer client_data; |
---|
803 | XtPointer call_data; |
---|
804 | { |
---|
805 | int buttonnum, entrynum; |
---|
806 | |
---|
807 | entrynum = ((int) client_data) >> 4; |
---|
808 | buttonnum = ((int) client_data) & 0x0F; |
---|
809 | |
---|
810 | switch (buttonnum) { |
---|
811 | |
---|
812 | case 0: |
---|
813 | if (TransactionNum(CURRENT) < TransactionNum(LAST)) |
---|
814 | GoToTransaction(NEXT, True); |
---|
815 | else |
---|
816 | GoToTransaction(CURRENT, True); |
---|
817 | break; |
---|
818 | |
---|
819 | case 1: |
---|
820 | GoToTransaction(PREV, True); |
---|
821 | break; |
---|
822 | case 2: |
---|
823 | GoToTransaction(NREF, True); |
---|
824 | break; |
---|
825 | case 3: |
---|
826 | GoToTransaction(PREF, True); |
---|
827 | break; |
---|
828 | case 4: |
---|
829 | switch (entrynum) { |
---|
830 | case 0: |
---|
831 | GetTransactionNum(); |
---|
832 | break; |
---|
833 | case 1: |
---|
834 | GoToTransaction(FIRST, True); |
---|
835 | break; |
---|
836 | case 2: |
---|
837 | GoToTransaction(LAST, True); |
---|
838 | break; |
---|
839 | case 3: |
---|
840 | GoToTransaction(FREF, True); |
---|
841 | break; |
---|
842 | case 4: |
---|
843 | GoToTransaction(LREF, True); |
---|
844 | break; |
---|
845 | } |
---|
846 | break; |
---|
847 | case 5: |
---|
848 | switch (entrynum) { |
---|
849 | case 0: |
---|
850 | if (axis[0] != ' ') |
---|
851 | SubmitTransaction(TransactionNum(CURRENT)); |
---|
852 | break; |
---|
853 | case 1: |
---|
854 | if (axis[6] != ' ') |
---|
855 | SubmitTransaction(0); |
---|
856 | break; |
---|
857 | } |
---|
858 | /* |
---|
859 | ** This makes the buttons update to reflect the new transaction. |
---|
860 | */ |
---|
861 | GoToTransaction(CURRENT, False); |
---|
862 | break; |
---|
863 | case 6: |
---|
864 | switch (entrynum) { |
---|
865 | case 0: |
---|
866 | WriteTransaction(TransactionNum(CURRENT)); |
---|
867 | break; |
---|
868 | case 1: |
---|
869 | break; |
---|
870 | } |
---|
871 | break; |
---|
872 | default: |
---|
873 | fprintf (stderr,"Stub function\n"); |
---|
874 | } |
---|
875 | |
---|
876 | } |
---|
877 | |
---|
878 | RestoreTopTextWidget() |
---|
879 | { |
---|
880 | Arg args[1]; |
---|
881 | unsigned int n; |
---|
882 | |
---|
883 | CheckButtonSensitivity(BUTTONS_ON); |
---|
884 | |
---|
885 | n = 0; |
---|
886 | XtSetArg(args[n], XtNstring, meetinglist); n++; |
---|
887 | XtSetValues (toptextW, args, n); |
---|
888 | PutUpArrow(toptextW, startOfCurrentMeeting, True); |
---|
889 | } |
---|
890 | |
---|
891 | |
---|
892 | |
---|
893 | static void |
---|
894 | QuitCB(w, client_data, call_data) |
---|
895 | Widget w; |
---|
896 | XtPointer client_data; |
---|
897 | XtPointer call_data; |
---|
898 | { |
---|
899 | (void) SaveMeetingNames("", ""); |
---|
900 | |
---|
901 | fputs("(quit)\n", outputfile); |
---|
902 | fflush (outputfile); |
---|
903 | exit (0); |
---|
904 | } |
---|
905 | |
---|
906 | static void |
---|
907 | HelpCB(w, client_data, call_data) |
---|
908 | Widget w; |
---|
909 | XtPointer client_data; |
---|
910 | XtPointer call_data; |
---|
911 | { |
---|
912 | PutUpHelp(); |
---|
913 | } |
---|
914 | |
---|
915 | /* |
---|
916 | ** HighlightNewItem...Change the highlighted line in the passed textwidget |
---|
917 | ** in the direction requested. Return 0 if successful, -1 if there was |
---|
918 | ** no meeting in that direction. |
---|
919 | */ |
---|
920 | |
---|
921 | HighlightNewItem(textW, mode, flag) |
---|
922 | Widget textW; /* list of meetings */ |
---|
923 | int mode; /* one of { NEXTNEWS, PREVNEWS, UPDATE, INITIALIZE} */ |
---|
924 | Boolean flag; /* update current meeting? */ |
---|
925 | { |
---|
926 | Arg args[5]; |
---|
927 | unsigned int n; |
---|
928 | XawTextPosition start, end, inspoint; |
---|
929 | char *tempstring, *foo, *tempptr; |
---|
930 | int length; |
---|
931 | char statusline[LONGNAMELEN + 25]; |
---|
932 | char longmtg[LONGNAMELEN]; |
---|
933 | char shortmtg[SHORTNAMELEN]; |
---|
934 | |
---|
935 | inspoint = XawTextGetInsertionPoint(textW); |
---|
936 | |
---|
937 | n = 0; |
---|
938 | XtSetArg(args[n], XtNstring, &tempstring); n++; |
---|
939 | XtGetValues (textW, args, n); |
---|
940 | |
---|
941 | if (tempstring[inspoint] == '\0') |
---|
942 | return (-1); |
---|
943 | |
---|
944 | /* |
---|
945 | ** Find start and end of current line. |
---|
946 | */ |
---|
947 | |
---|
948 | for (start = inspoint; start && tempstring[start-1] != '\n'; start--) |
---|
949 | ; |
---|
950 | for ( end = inspoint; |
---|
951 | tempstring[end] != '\0' && tempstring[end] != '\n'; |
---|
952 | end++) |
---|
953 | ; |
---|
954 | |
---|
955 | /* |
---|
956 | ** Special case for initializing: change mode to NEXTNEWS unless we're |
---|
957 | ** already on a line with unread transactions. Do nothing in simplemode, |
---|
958 | ** because we always want to stay on the first line. |
---|
959 | */ |
---|
960 | if (mode == INITIALIZE && simplemode != True) { |
---|
961 | if ( tempstring[start + 2] != 'c') |
---|
962 | mode = NEXTNEWS; |
---|
963 | } |
---|
964 | |
---|
965 | if (mode == NEXTNEWS) { |
---|
966 | |
---|
967 | if (start == end || tempstring[end] == '\0') { |
---|
968 | PutUpWarning( "", |
---|
969 | "Nothing more to read", False); |
---|
970 | return(-1); |
---|
971 | } |
---|
972 | |
---|
973 | do { |
---|
974 | if (tempstring[end] == '\n') { |
---|
975 | start = end + 1; |
---|
976 | } |
---|
977 | end = start + strcspn (tempstring + start, "\n\0"); |
---|
978 | } while ( tempstring[end] != '\0' && |
---|
979 | tempstring[start + 2] != 'c'); |
---|
980 | |
---|
981 | |
---|
982 | if ( tempstring[start] == '\0') { |
---|
983 | PutUpWarning( "", |
---|
984 | "Nothing more to read", False); |
---|
985 | return(-1); |
---|
986 | } |
---|
987 | |
---|
988 | } |
---|
989 | |
---|
990 | else if (mode == PREVNEWS) { |
---|
991 | if (start == 0) { |
---|
992 | PutUpWarning( "", |
---|
993 | "no previous meeting with unread news", False); |
---|
994 | return(-1); |
---|
995 | } |
---|
996 | do { |
---|
997 | end = start - 1; |
---|
998 | for ( start = end - 1; |
---|
999 | start > 0 && tempstring[start] != '\n'; |
---|
1000 | start--) |
---|
1001 | ; |
---|
1002 | if (start != 0) start++; |
---|
1003 | } while ( start && |
---|
1004 | tempstring[start + 2] != 'c'); |
---|
1005 | if ( tempstring[start + 2] != 'c' ) { |
---|
1006 | PutUpWarning( "", |
---|
1007 | "no previous meeting with unread news", False); |
---|
1008 | return(-1); |
---|
1009 | } |
---|
1010 | } |
---|
1011 | |
---|
1012 | else if (mode == UPDATE) { |
---|
1013 | /* |
---|
1014 | ** Just need to update current meeting to match highlighted item. |
---|
1015 | */ |
---|
1016 | } |
---|
1017 | |
---|
1018 | PutUpArrow(textW, start, True); |
---|
1019 | |
---|
1020 | if (flag) { |
---|
1021 | length = (end - start); |
---|
1022 | foo = (char *) calloc (length + 1, sizeof(char)); |
---|
1023 | strncpy (foo, tempstring + start + 8, length - 8); |
---|
1024 | tempptr = strchr (foo, ','); |
---|
1025 | *tempptr = '\0'; |
---|
1026 | strcpy (longmtg, foo); |
---|
1027 | strcpy (shortmtg, tempptr + 2); |
---|
1028 | |
---|
1029 | free (foo); |
---|
1030 | } |
---|
1031 | |
---|
1032 | if (SaveMeetingNames(longmtg, shortmtg) == -1) { |
---|
1033 | PutUpStatusMessage("No current meeting"); |
---|
1034 | CheckButtonSensitivity(BUTTONS_OFF); |
---|
1035 | return (-1); |
---|
1036 | } |
---|
1037 | CheckButtonSensitivity(BUTTONS_ON); |
---|
1038 | |
---|
1039 | sprintf (statusline, "Reading %s [%d-%d]", |
---|
1040 | longmtg, |
---|
1041 | TransactionNum(FIRST), |
---|
1042 | TransactionNum(LAST)); |
---|
1043 | |
---|
1044 | PutUpStatusMessage(statusline); |
---|
1045 | |
---|
1046 | XFlush(XtDisplay(textW)); |
---|
1047 | return(0); |
---|
1048 | } |
---|
1049 | |
---|
1050 | |
---|
1051 | /* |
---|
1052 | ** Run the command. If textW and filename are passed, |
---|
1053 | ** read the contents of filename after running the command |
---|
1054 | ** and put them into textW. |
---|
1055 | ** |
---|
1056 | ** If returnvalue is NULL, don't wait for a response from the |
---|
1057 | ** command. Otherwise, return a pointer to the return value, |
---|
1058 | ** which must be freed by the calling routine. |
---|
1059 | ** |
---|
1060 | ** This version uses byte-by-byte i/o so it can recognize \n |
---|
1061 | ** as end-of-data. Can't use fgets because we don't know |
---|
1062 | ** how long the data stream is, and need to keep reallocing. |
---|
1063 | ** |
---|
1064 | ** Return -1 on error. |
---|
1065 | */ |
---|
1066 | |
---|
1067 | char * |
---|
1068 | RunCommand (command, textW, filename, returnvalue) |
---|
1069 | char *command; |
---|
1070 | Widget textW; |
---|
1071 | char *filename; |
---|
1072 | Boolean returnvalue; |
---|
1073 | { |
---|
1074 | char *message; |
---|
1075 | int cursize = BUFSIZE; |
---|
1076 | int curbyte = 0; |
---|
1077 | |
---|
1078 | /* |
---|
1079 | ** Send command to child's input stream |
---|
1080 | */ |
---|
1081 | if (fputs(command, outputfile) == EOF) { |
---|
1082 | fprintf (stderr, "Error on fputs\n"); |
---|
1083 | return ((char *)-1); |
---|
1084 | } |
---|
1085 | fflush (outputfile); |
---|
1086 | |
---|
1087 | if (debug) |
---|
1088 | fprintf (stderr, "appl: %s\n",command); |
---|
1089 | fflush (stderr); |
---|
1090 | |
---|
1091 | if (!returnvalue) |
---|
1092 | return (NULL); |
---|
1093 | /* |
---|
1094 | ** Look for child's (one-line) response |
---|
1095 | */ |
---|
1096 | |
---|
1097 | READLINE: |
---|
1098 | |
---|
1099 | message = (char *) malloc (BUFSIZE); |
---|
1100 | |
---|
1101 | while (( message [cursize - BUFSIZE + curbyte] = |
---|
1102 | fgetc (inputfile)) != '\n') { |
---|
1103 | |
---|
1104 | curbyte++; |
---|
1105 | if (curbyte == BUFSIZE) { |
---|
1106 | cursize += BUFSIZE; |
---|
1107 | curbyte = 0; |
---|
1108 | message = (char *) realloc (message, cursize); |
---|
1109 | } |
---|
1110 | } |
---|
1111 | |
---|
1112 | message[cursize - BUFSIZE + curbyte] = '\0'; |
---|
1113 | |
---|
1114 | if (debug) |
---|
1115 | fprintf (stderr, "edsc: %s\n",message); |
---|
1116 | |
---|
1117 | if (message[0] == ';' ) { |
---|
1118 | PutUpWarning("ERROR", message + 1, False); |
---|
1119 | myfree (message); |
---|
1120 | return ((char *)-1); |
---|
1121 | } |
---|
1122 | |
---|
1123 | if (message[0] == '-') { |
---|
1124 | PutUpWarning("WARNING", message + 1, False); |
---|
1125 | myfree (message); |
---|
1126 | curbyte = 0; |
---|
1127 | cursize = BUFSIZE; |
---|
1128 | goto READLINE; |
---|
1129 | } |
---|
1130 | /* |
---|
1131 | ** Read the verbose response and put it into the text widget |
---|
1132 | */ |
---|
1133 | if (filename && textW) |
---|
1134 | FileIntoWidget(filename, textW); |
---|
1135 | |
---|
1136 | return (message); |
---|
1137 | } |
---|
1138 | |
---|
1139 | |
---|
1140 | FileIntoWidget(filename, textW) |
---|
1141 | char *filename; |
---|
1142 | TextWidget textW; |
---|
1143 | { |
---|
1144 | unsigned int fd; |
---|
1145 | Arg args[5]; |
---|
1146 | char *message; |
---|
1147 | int cursize = BUFSIZE; |
---|
1148 | int numread = 1, n; |
---|
1149 | char errormsg[80]; |
---|
1150 | |
---|
1151 | fd = open(filename, O_RDONLY); |
---|
1152 | |
---|
1153 | if (fd == -1) { |
---|
1154 | sprintf (errormsg,"Error opening file %s\n",filename); |
---|
1155 | PutUpWarning("WARNING", errormsg, False); |
---|
1156 | return (-1); |
---|
1157 | } |
---|
1158 | |
---|
1159 | /* |
---|
1160 | ** Make certain we don't try to erase the (now nonexistant) plus sign. |
---|
1161 | */ |
---|
1162 | if (textW == toptextW) |
---|
1163 | oldarrow = -1; |
---|
1164 | |
---|
1165 | message = (char*) malloc (cursize); |
---|
1166 | |
---|
1167 | while (!HELL_FROZEN_OVER) { |
---|
1168 | numread = read (fd, message + cursize - BUFSIZE, BUFSIZE); |
---|
1169 | if (numread == -1) { |
---|
1170 | sprintf (errormsg,"Error reading from file %s\n",filename); |
---|
1171 | PutUpWarning("WARNING", errormsg, False); |
---|
1172 | close (fd); |
---|
1173 | return(-1); |
---|
1174 | } |
---|
1175 | if (numread < BUFSIZE) |
---|
1176 | break; |
---|
1177 | |
---|
1178 | cursize += BUFSIZE; |
---|
1179 | message = (char*) realloc (message, cursize); |
---|
1180 | } |
---|
1181 | |
---|
1182 | if (*message) { |
---|
1183 | message[cursize - BUFSIZE + numread] = '\0'; |
---|
1184 | n = 0; |
---|
1185 | XtSetArg (args[n], XtNstring, message); n++; |
---|
1186 | XtSetValues (textW, args, n); |
---|
1187 | } |
---|
1188 | else { |
---|
1189 | PutUpWarning( "", |
---|
1190 | "No text in this transaction", False); |
---|
1191 | XBell (XtDisplay(textW), 0); |
---|
1192 | |
---|
1193 | } |
---|
1194 | |
---|
1195 | XFlush(XtDisplay(textW)); |
---|
1196 | |
---|
1197 | myfree (message); |
---|
1198 | close (fd); |
---|
1199 | return(0); |
---|
1200 | } |
---|
1201 | |
---|
1202 | static void |
---|
1203 | CheckEdscVersion() |
---|
1204 | { |
---|
1205 | char *version; |
---|
1206 | |
---|
1207 | version = RunCommand ("(gpv)\n", NULL, NULL, True); |
---|
1208 | |
---|
1209 | if ((int) version == -1) { |
---|
1210 | fprintf (stderr, "Cannot communicate with edsc.\n"); |
---|
1211 | exit (-1); |
---|
1212 | } |
---|
1213 | |
---|
1214 | edscversion = atoi(version + 1); |
---|
1215 | |
---|
1216 | if (edscversion < 24) { |
---|
1217 | fprintf (stderr, "Caution...using edsc version %1.1f. ",(float) edscversion/10.0); |
---|
1218 | fprintf (stderr, "Should be using at least 2.4.\n"); |
---|
1219 | } |
---|
1220 | |
---|
1221 | nocache = (edscversion >= 25) ? True : False; |
---|
1222 | } |
---|
1223 | |
---|
1224 | ParseMeetingsFile() |
---|
1225 | { |
---|
1226 | char *fulllist; |
---|
1227 | char *movingptr; |
---|
1228 | char *firstquote, *secondquote; |
---|
1229 | int status; |
---|
1230 | char fullname[100], shortname[100]; |
---|
1231 | int i; |
---|
1232 | |
---|
1233 | fulllist = RunCommand ("(gml)\n", NULL, NULL, True); |
---|
1234 | if ((int) fulllist <= 0) return; |
---|
1235 | |
---|
1236 | if (meetinglist) |
---|
1237 | myfree (meetinglist); |
---|
1238 | |
---|
1239 | i = strlen(fulllist) * 2; |
---|
1240 | meetinglist = (char *) calloc (i, sizeof(char)); |
---|
1241 | if (debug) fprintf (stderr, "Allocated %x, %d long\n", meetinglist, i); |
---|
1242 | |
---|
1243 | secondquote = fulllist; |
---|
1244 | |
---|
1245 | for (i = 0; ; i++) { |
---|
1246 | |
---|
1247 | movingptr = strchr (secondquote + 1, '('); |
---|
1248 | |
---|
1249 | if (!movingptr) |
---|
1250 | break; |
---|
1251 | |
---|
1252 | movingptr++; |
---|
1253 | |
---|
1254 | status = atoi(movingptr); |
---|
1255 | |
---|
1256 | firstquote = strchr(movingptr, '"'); |
---|
1257 | secondquote = strchr(firstquote+1, '"'); |
---|
1258 | *secondquote = '\0'; |
---|
1259 | strcpy (fullname, firstquote + 1); |
---|
1260 | |
---|
1261 | if (*(secondquote + 1) == ')') { |
---|
1262 | *shortname = '\0'; |
---|
1263 | } |
---|
1264 | |
---|
1265 | else { |
---|
1266 | firstquote = strchr(secondquote+1, '"'); |
---|
1267 | secondquote = strchr(firstquote+1, '"'); |
---|
1268 | *secondquote = '\0'; |
---|
1269 | strcpy (shortname, firstquote + 1); |
---|
1270 | } |
---|
1271 | |
---|
1272 | if (debug) |
---|
1273 | fprintf (stderr, "Got %d, '%s', '%s'\n", |
---|
1274 | status, fullname, shortname); |
---|
1275 | |
---|
1276 | sprintf (meetinglist, "%s %c %s, %s\n", |
---|
1277 | meetinglist, |
---|
1278 | status ? 'c' : ' ', |
---|
1279 | fullname, shortname); |
---|
1280 | } |
---|
1281 | |
---|
1282 | sprintf (meetinglist, "%s\0",meetinglist); |
---|
1283 | myfree(fulllist); |
---|
1284 | if (debug) fprintf (stderr, "Actually used %d\n", strlen(meetinglist)); |
---|
1285 | } |
---|
1286 | |
---|
1287 | myfree(ptr) |
---|
1288 | char *ptr; |
---|
1289 | { |
---|
1290 | if ((int)ptr > 0) { |
---|
1291 | if (debug) fprintf (stderr, "Freeing %x\n",ptr); |
---|
1292 | free(ptr); |
---|
1293 | } |
---|
1294 | else if (debug) fprintf (stderr, "Not freeing %x\n",ptr); |
---|
1295 | } |
---|
1296 | |
---|
1297 | /* |
---|
1298 | ** An item in the upper text window has been clicked on. If it is a |
---|
1299 | ** meeting, move there and put the first transaction on the screen. |
---|
1300 | ** If it's a transaction, we display it in the lower window. |
---|
1301 | */ |
---|
1302 | |
---|
1303 | void |
---|
1304 | Update() |
---|
1305 | { |
---|
1306 | if (topscreen == MAIN) { |
---|
1307 | (void) MoveToMeeting(UPDATE); |
---|
1308 | } |
---|
1309 | else if (topscreen == LISTTRNS) { |
---|
1310 | GoToTransaction(HighlightedTransaction(), True); |
---|
1311 | } |
---|
1312 | } |
---|
1313 | |
---|
1314 | |
---|
1315 | void |
---|
1316 | Stub() |
---|
1317 | { |
---|
1318 | } |
---|
1319 | |
---|
1320 | void |
---|
1321 | PrintEvent(w, event, params, num_params) |
---|
1322 | Widget w; |
---|
1323 | XEvent *event; |
---|
1324 | String *params; |
---|
1325 | int *num_params; |
---|
1326 | { |
---|
1327 | fprintf(stderr, "event type %d for widget %s\n", |
---|
1328 | event->type, XtName(w)); |
---|
1329 | } |
---|
1330 | |
---|
1331 | |
---|
1332 | /* |
---|
1333 | ** If we're reading a transaction, scroll it one page down. |
---|
1334 | ** If we're at the end of a transaction, go to the next one. |
---|
1335 | ** If we're at the end of a meeting, find the next one with unread |
---|
1336 | ** transactions. |
---|
1337 | */ |
---|
1338 | |
---|
1339 | static void |
---|
1340 | DoTheRightThing() |
---|
1341 | { |
---|
1342 | if (PopdownCB(NULL, NULL, NULL)) |
---|
1343 | return; |
---|
1344 | |
---|
1345 | if (!TryToScrollAPage(bottextW,1)) { |
---|
1346 | return; |
---|
1347 | } |
---|
1348 | |
---|
1349 | /* |
---|
1350 | ** Are we at the end of a meeting? |
---|
1351 | */ |
---|
1352 | if (TransactionNum(NEXT) != 0) { |
---|
1353 | /* |
---|
1354 | ** No, read the next transaction |
---|
1355 | */ |
---|
1356 | BotSelect(NULL, 0, NULL); |
---|
1357 | } |
---|
1358 | else { |
---|
1359 | /* |
---|
1360 | ** Yes, go to the next meeting and read its next transaction. |
---|
1361 | */ |
---|
1362 | if ((simplemode != True) && (MoveToMeeting(NEXTNEWS) == 0)) { |
---|
1363 | BotSelect(NULL, 0, NULL); |
---|
1364 | } |
---|
1365 | } |
---|
1366 | } |
---|
1367 | |
---|
1368 | static void |
---|
1369 | DoTheRightThingInReverse() |
---|
1370 | { |
---|
1371 | if (!TryToScrollAPage(bottextW,-1)) { |
---|
1372 | return; |
---|
1373 | } |
---|
1374 | |
---|
1375 | /* |
---|
1376 | ** Are we at the start of a meeting? |
---|
1377 | */ |
---|
1378 | if (TransactionNum(CURRENT) > TransactionNum(FIRST)) { |
---|
1379 | /* |
---|
1380 | ** No, read the prev transaction |
---|
1381 | */ |
---|
1382 | BotSelect(NULL, (XtPointer)1, NULL); |
---|
1383 | } |
---|
1384 | else { |
---|
1385 | /* |
---|
1386 | ** Yes, go to the prev meeting and read its next transaction. |
---|
1387 | */ |
---|
1388 | TopSelect(NULL, (XtPointer)1, NULL); |
---|
1389 | } |
---|
1390 | } |
---|
1391 | |
---|
1392 | /* |
---|
1393 | ** Code stolen from Text.c and TextAction.c to scroll the text widget. |
---|
1394 | ** Many text functions are static, so I had to take what I could get. |
---|
1395 | */ |
---|
1396 | |
---|
1397 | TryToScrollAPage(ctx, direction) |
---|
1398 | TextWidget ctx; |
---|
1399 | int direction; |
---|
1400 | { |
---|
1401 | int scroll_val = (ctx->text.lt.lines - 1) * direction; |
---|
1402 | |
---|
1403 | /* |
---|
1404 | ** Don't scroll off the bottom |
---|
1405 | */ |
---|
1406 | if (ctx->text.lt.info[ctx->text.lt.lines].position > |
---|
1407 | ctx->text.lastPos && |
---|
1408 | direction > 0) { |
---|
1409 | return (-1); |
---|
1410 | } |
---|
1411 | /* |
---|
1412 | ** Don't scroll off the top |
---|
1413 | */ |
---|
1414 | if (ctx->text.lt.top == 0 && |
---|
1415 | direction < 0) { |
---|
1416 | return (-1); |
---|
1417 | } |
---|
1418 | |
---|
1419 | _XawTextPrepareToUpdate(ctx); |
---|
1420 | _XawTextVScroll(ctx, scroll_val); |
---|
1421 | |
---|
1422 | ctx->text.insertPos = ctx->text.lt.top; |
---|
1423 | _XawTextCheckResize(ctx); |
---|
1424 | _XawTextExecuteUpdate(ctx); |
---|
1425 | ctx->text.mult = 1; |
---|
1426 | return (0); |
---|
1427 | } |
---|
1428 | |
---|
1429 | |
---|
1430 | static char oldline[80]; |
---|
1431 | |
---|
1432 | PutUpTempMessage(string) |
---|
1433 | char *string; |
---|
1434 | { |
---|
1435 | char *returndata; |
---|
1436 | Arg args[1]; |
---|
1437 | |
---|
1438 | XtSetArg(args[0], XtNstring, &returndata); |
---|
1439 | XtGetValues (label1W, args, 1); |
---|
1440 | strcpy (oldline, returndata); |
---|
1441 | |
---|
1442 | XtSetArg(args[0], XtNstring, string); |
---|
1443 | XtSetValues (label1W, args, 1); |
---|
1444 | XFlush(XtDisplay(label1W)); |
---|
1445 | } |
---|
1446 | |
---|
1447 | TakeDownTempMessage() |
---|
1448 | { |
---|
1449 | Arg args[1]; |
---|
1450 | |
---|
1451 | XtSetArg(args[0], XtNstring, oldline); |
---|
1452 | XtSetValues (label1W, args, 1); |
---|
1453 | } |
---|
1454 | |
---|
1455 | PutUpStatusMessage(string) |
---|
1456 | char *string; |
---|
1457 | { |
---|
1458 | Arg args[1]; |
---|
1459 | |
---|
1460 | XtSetArg(args[0], XtNstring, string); |
---|
1461 | XtSetValues (label1W, args, 1); |
---|
1462 | XFlush(XtDisplay(label1W)); |
---|
1463 | } |
---|
1464 | |
---|
1465 | /* |
---|
1466 | ** PutUpArrow assumes that "start" is the first character position of a line |
---|
1467 | ** in a text widget. It puts a marker "+" on this line, and if moveinsert |
---|
1468 | ** is True, moves the insert point there. |
---|
1469 | */ |
---|
1470 | |
---|
1471 | PutUpArrow(textW, start, moveinsert) |
---|
1472 | TextWidget textW; |
---|
1473 | XawTextPosition start; |
---|
1474 | Boolean moveinsert; |
---|
1475 | { |
---|
1476 | XawTextBlock textblock; |
---|
1477 | static int oldtopscreen = -1; |
---|
1478 | int offset; |
---|
1479 | XawTextPosition oldinspoint; |
---|
1480 | |
---|
1481 | offset = (topscreen == MAIN) ? 7 : 0; |
---|
1482 | |
---|
1483 | oldinspoint = XawTextGetInsertionPoint(textW); |
---|
1484 | |
---|
1485 | /* |
---|
1486 | ** Don't try to erase an arrow on another top screen |
---|
1487 | */ |
---|
1488 | if (topscreen != oldtopscreen) |
---|
1489 | oldarrow = -1; |
---|
1490 | |
---|
1491 | oldtopscreen = topscreen; |
---|
1492 | |
---|
1493 | textblock.firstPos = 0; |
---|
1494 | textblock.length = 1; |
---|
1495 | textblock.format = FMT8BIT; |
---|
1496 | |
---|
1497 | if (oldarrow != -1) { |
---|
1498 | textblock.ptr = " "; |
---|
1499 | XawTextReplace ( textW, oldarrow + offset, |
---|
1500 | oldarrow + offset + 1, &textblock); |
---|
1501 | } |
---|
1502 | |
---|
1503 | textblock.ptr = "+"; |
---|
1504 | |
---|
1505 | XawTextReplace ( textW, start + offset, |
---|
1506 | start + offset + 1, &textblock); |
---|
1507 | |
---|
1508 | if (moveinsert) |
---|
1509 | XawTextSetInsertionPoint (textW, start); |
---|
1510 | else |
---|
1511 | XawTextSetInsertionPoint (textW, oldinspoint); |
---|
1512 | |
---|
1513 | if (topscreen == MAIN) |
---|
1514 | startOfCurrentMeeting = start; |
---|
1515 | |
---|
1516 | XFlush(XtDisplay(textW)); |
---|
1517 | |
---|
1518 | oldarrow = start; |
---|
1519 | } |
---|
1520 | |
---|
1521 | /* |
---|
1522 | ** This assumes the insert position is at the start of the line containing |
---|
1523 | ** the letter 'c'. |
---|
1524 | */ |
---|
1525 | |
---|
1526 | /* |
---|
1527 | ** If UseStringInPlace were True for toptextW, we |
---|
1528 | ** wouldn't need both the XawTextReplace and the setting of |
---|
1529 | ** the char in meetinglist, but setting it to True causes weird |
---|
1530 | ** memory overlaps I haven't figured out yet. |
---|
1531 | */ |
---|
1532 | |
---|
1533 | void |
---|
1534 | RemoveLetterC() |
---|
1535 | { |
---|
1536 | XawTextBlock textblock; |
---|
1537 | XawTextPosition inspoint; |
---|
1538 | |
---|
1539 | textblock.firstPos = 0; |
---|
1540 | textblock.length = 1; |
---|
1541 | textblock.format = FMT8BIT; |
---|
1542 | textblock.ptr = " "; |
---|
1543 | |
---|
1544 | inspoint = startOfCurrentMeeting; |
---|
1545 | |
---|
1546 | if (inspoint > strlen (meetinglist)) |
---|
1547 | return; |
---|
1548 | |
---|
1549 | XawTextReplace (toptextW, inspoint + 2, inspoint + 3, &textblock); |
---|
1550 | |
---|
1551 | *(meetinglist + inspoint + 2) = ' '; |
---|
1552 | |
---|
1553 | XFlush(XtDisplay(toptextW)); |
---|
1554 | } |
---|
1555 | |
---|
1556 | AddChildren (parent, whichone) |
---|
1557 | Widget parent; |
---|
1558 | int whichone; |
---|
1559 | { |
---|
1560 | Widget command, menu, entry; |
---|
1561 | int i, j, n; |
---|
1562 | char *name, *label; |
---|
1563 | Arg args[5]; |
---|
1564 | EntryRec *toprec, *newrec; |
---|
1565 | void (*mycallback)(); |
---|
1566 | |
---|
1567 | char **buttonlabels; |
---|
1568 | char **buttonnames; |
---|
1569 | |
---|
1570 | if (whichone == 0) { |
---|
1571 | buttonlabels = menu_labels0; |
---|
1572 | buttonnames = menu_names0; |
---|
1573 | mycallback = TopSelect; |
---|
1574 | } |
---|
1575 | else { |
---|
1576 | buttonlabels = menu_labels1; |
---|
1577 | buttonnames = menu_names1; |
---|
1578 | mycallback = BotSelect; |
---|
1579 | } |
---|
1580 | |
---|
1581 | for (i = 0; i < MAX_BUTTONS && buttonnames[i]; i++) { |
---|
1582 | n = 0; |
---|
1583 | XtSetArg(args[n], XtNmenuName, buttonlabels[i]); n++; |
---|
1584 | XtSetArg(args[n], XtNlabel, buttonlabels[i]); n++; |
---|
1585 | |
---|
1586 | if (whichone == 0) { |
---|
1587 | label = submenu_labels0[i][0]; |
---|
1588 | name = submenu_names0[i][0]; |
---|
1589 | } |
---|
1590 | else { |
---|
1591 | label = submenu_labels1[i][0]; |
---|
1592 | name = submenu_names1[i][0]; |
---|
1593 | } |
---|
1594 | toprec = &(toplevelbuttons[whichone][i]); |
---|
1595 | |
---|
1596 | if (name) { |
---|
1597 | command = XtCreateManagedWidget( |
---|
1598 | buttonnames[i], |
---|
1599 | menuButtonWidgetClass, parent, |
---|
1600 | args, n); |
---|
1601 | } |
---|
1602 | else { |
---|
1603 | command = XtCreateManagedWidget( |
---|
1604 | buttonnames[i], |
---|
1605 | commandWidgetClass, parent, |
---|
1606 | args, n); |
---|
1607 | XtAddCallback( command, XtNcallback, |
---|
1608 | mycallback, (XtPointer) i); |
---|
1609 | } |
---|
1610 | |
---|
1611 | toprec->button = command; |
---|
1612 | toprec->nextrec = NULL; |
---|
1613 | |
---|
1614 | XtInstallAccelerators(topW, command); |
---|
1615 | |
---|
1616 | if (!name) |
---|
1617 | continue; |
---|
1618 | |
---|
1619 | /* |
---|
1620 | ** Add menus to menu buttons. |
---|
1621 | */ |
---|
1622 | |
---|
1623 | n = 0; |
---|
1624 | menu = XtCreatePopupShell( |
---|
1625 | buttonlabels[i], |
---|
1626 | simpleMenuWidgetClass, |
---|
1627 | parent, |
---|
1628 | args, n); |
---|
1629 | |
---|
1630 | for (j = 0; j < MAX_MENU_LEN; j++) { |
---|
1631 | if (whichone == 0) { |
---|
1632 | label = submenu_labels0[i][j]; |
---|
1633 | name = submenu_names0[i][j]; |
---|
1634 | } |
---|
1635 | else { |
---|
1636 | label = submenu_labels1[i][j]; |
---|
1637 | name = submenu_names1[i][j]; |
---|
1638 | } |
---|
1639 | if (!name) |
---|
1640 | break; |
---|
1641 | |
---|
1642 | newrec = (EntryRec *) malloc (sizeof (EntryRec)); |
---|
1643 | toprec->nextrec = newrec; |
---|
1644 | newrec->nextrec = NULL; |
---|
1645 | n = 0; |
---|
1646 | XtSetArg(args[n], XtNlabel, label); n++; |
---|
1647 | |
---|
1648 | entry = XtCreateManagedWidget( |
---|
1649 | name, smeBSBObjectClass, menu, |
---|
1650 | args, n); |
---|
1651 | XtAddCallback( entry, XtNcallback, |
---|
1652 | mycallback, |
---|
1653 | (XtPointer) (i + (j << 4))); |
---|
1654 | newrec->button = entry; |
---|
1655 | toprec = newrec; |
---|
1656 | } |
---|
1657 | } |
---|
1658 | } |
---|
1659 | |
---|
1660 | /* |
---|
1661 | ** A keyboard equivalent has been hit. For normal command widgets, send |
---|
1662 | ** them a button-one-down and button-one-up. For menu buttons, just send |
---|
1663 | ** them the button-down, and their child will send the button-up. |
---|
1664 | */ |
---|
1665 | |
---|
1666 | static void |
---|
1667 | KeyCallback(w, event, params, num_params) |
---|
1668 | Widget w; |
---|
1669 | XEvent *event; |
---|
1670 | String *params; |
---|
1671 | int *num_params; |
---|
1672 | { |
---|
1673 | Widget button; |
---|
1674 | XButtonEvent MyEvent; |
---|
1675 | int i, whichrow; |
---|
1676 | |
---|
1677 | if (*num_params < 1) |
---|
1678 | return; |
---|
1679 | |
---|
1680 | for (i = 0; i < MAX_BUTTONS; i++) { |
---|
1681 | |
---|
1682 | if (menu_names0[i] && !strcmp (params[0], menu_names0[i])) { |
---|
1683 | whichrow = 0; |
---|
1684 | break; |
---|
1685 | } |
---|
1686 | |
---|
1687 | if (menu_names1[i] && !strcmp (params[0], menu_names1[i])) { |
---|
1688 | whichrow = 1; |
---|
1689 | break; |
---|
1690 | } |
---|
1691 | } |
---|
1692 | |
---|
1693 | if (i == MAX_BUTTONS) { |
---|
1694 | fprintf (stderr, "Key not found. Aborting.\n"); |
---|
1695 | return; |
---|
1696 | } |
---|
1697 | |
---|
1698 | button = (toplevelbuttons[whichrow][i]).button; |
---|
1699 | |
---|
1700 | MyEvent.type = ButtonPress; |
---|
1701 | MyEvent.display = dpy; |
---|
1702 | MyEvent.window = XtWindow(button); |
---|
1703 | MyEvent.button = 1; |
---|
1704 | MyEvent.x = 1; |
---|
1705 | MyEvent.y = 1; |
---|
1706 | MyEvent.state = ButtonPressMask; |
---|
1707 | XSendEvent( dpy, |
---|
1708 | XtWindow(button), |
---|
1709 | False, |
---|
1710 | ButtonPressMask, |
---|
1711 | (XEvent *) &MyEvent); |
---|
1712 | |
---|
1713 | XSync(dpy, False); |
---|
1714 | if (!(toplevelbuttons[whichrow][i]).nextrec) { |
---|
1715 | MyEvent.type = ButtonRelease; |
---|
1716 | MyEvent.state = ButtonReleaseMask; |
---|
1717 | XSendEvent( dpy, |
---|
1718 | XtWindow(button), |
---|
1719 | False, |
---|
1720 | ButtonReleaseMask, |
---|
1721 | (XEvent *) &MyEvent); |
---|
1722 | } |
---|
1723 | |
---|
1724 | } |
---|
1725 | |
---|
1726 | /* |
---|
1727 | ** Check time interval between mouse clicks. If it's less than the |
---|
1728 | ** intrinsics' multi-click timer, call my own "Update" procedure. |
---|
1729 | ** Otherwise, pass the click on to the text widget. |
---|
1730 | */ |
---|
1731 | |
---|
1732 | void |
---|
1733 | DispatchClick(w, event, params, num_params) |
---|
1734 | Widget w; |
---|
1735 | XEvent *event; |
---|
1736 | String *params; /* unused */ |
---|
1737 | Cardinal *num_params; /* unused */ |
---|
1738 | { |
---|
1739 | static Time lasttime = 0; |
---|
1740 | |
---|
1741 | if ( lasttime == 0 || |
---|
1742 | (XtLastTimestampProcessed(XtDisplay(w)) - lasttime) > |
---|
1743 | (Time) XtGetMultiClickTime(XtDisplay(w))) { |
---|
1744 | XtCallActionProc(w, "select-start", event, |
---|
1745 | params, *num_params); |
---|
1746 | } |
---|
1747 | else { |
---|
1748 | XtCallActionProc(w, "Update", event, |
---|
1749 | params, *num_params); |
---|
1750 | } |
---|
1751 | lasttime = XtLastTimestampProcessed(XtDisplay(w)); |
---|
1752 | } |
---|
1753 | |
---|
1754 | /* |
---|
1755 | * Function: GetFontWidth(widget) |
---|
1756 | * based on code from Xaw/TextSink.c |
---|
1757 | * mdb 7/26/96 |
---|
1758 | */ |
---|
1759 | |
---|
1760 | static unsigned long |
---|
1761 | GetFontWidth(w) |
---|
1762 | Widget w; |
---|
1763 | { |
---|
1764 | TextSinkObject sink = (TextSinkObject) w; |
---|
1765 | Atom XA_FIGURE_WIDTH; |
---|
1766 | unsigned long figure_width = 0; |
---|
1767 | XFontStruct *font; |
---|
1768 | Arg args[1]; |
---|
1769 | |
---|
1770 | XtSetArg(args[0], XtNfont, &font); |
---|
1771 | XtGetValues (w, args, 1); |
---|
1772 | |
---|
1773 | /* |
---|
1774 | * Find the figure width of the current font. |
---|
1775 | */ |
---|
1776 | |
---|
1777 | XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", FALSE); |
---|
1778 | if ( XA_FIGURE_WIDTH != None && |
---|
1779 | ( (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)) || |
---|
1780 | (figure_width == 0)) ) |
---|
1781 | if (font->per_char && font->min_char_or_byte2 <= '$' && |
---|
1782 | font->max_char_or_byte2 >= '$') |
---|
1783 | figure_width = font->per_char['$' - font->min_char_or_byte2].width; |
---|
1784 | else |
---|
1785 | figure_width = font->max_bounds.width; |
---|
1786 | |
---|
1787 | return(figure_width); |
---|
1788 | } |
---|