1 | /* stderr */ |
---|
2 | |
---|
3 | /* Interface |
---|
4 | By Sean T. Lamont |
---|
5 | For use with the Macntosh version of the Phylogeny Inference Package, |
---|
6 | version 3.5c. (c) Copyright 1992 by Joseph Felsenstein. |
---|
7 | Permission is granted to copy and use this program provided no fee is |
---|
8 | charged for it and provided that this copyright notice is not removed. |
---|
9 | |
---|
10 | This file defines a 2-window environment which replicates many |
---|
11 | of the standard c I/O functions (puts, printf,gets,scanf) |
---|
12 | in a maclike environment, with a scrollback buffer. This |
---|
13 | is necessary because of the very weak implementation of IO under |
---|
14 | straight C, and the difficulty of using separate windows. It also |
---|
15 | adds the ability to "quit" out of an application while it is running, |
---|
16 | and some very basic point-and-click interface type of stuff on the |
---|
17 | screen. |
---|
18 | |
---|
19 | Functions you need to know how to use: |
---|
20 | macsetup(char *name): initializes the interface, brings up a window of |
---|
21 | the name of the argument, for I/O. |
---|
22 | macprintf(char *string,arg,arg): like printf but into the window |
---|
23 | macgets(char *string); like puts but into the window |
---|
24 | macscanf(char *string, arg,arg) like scanf but from the window |
---|
25 | macgets (char *string,arg,arg) like gets but from the window. |
---|
26 | |
---|
27 | It is recommended that you include "interface.h" file, which sets |
---|
28 | up these #define's for you (IE all calls to scanf will call |
---|
29 | macscanf, etc.) |
---|
30 | |
---|
31 | textmode(); makes the current drawing window the text window |
---|
32 | gfxmode(); makes the current drawing window the gfx window, |
---|
33 | unhides the graphics window. |
---|
34 | |
---|
35 | eventloop(): process mouse events, menus, etc., and wait for |
---|
36 | "go away" event. You are implicitly doing this\ |
---|
37 | when you run macgets/macscanf. If you want to query |
---|
38 | the event handler during non-IO periods of time this |
---|
39 | would be what to call (or alternatively, printf(""); |
---|
40 | */ |
---|
41 | |
---|
42 | |
---|
43 | #include <stdarg.h> |
---|
44 | #include <stdio.h> |
---|
45 | #include "interface.h" |
---|
46 | |
---|
47 | #define SCROLLLINES 250 |
---|
48 | |
---|
49 | #define SCROLLCOLUMNS 80 |
---|
50 | #define SCROLLMEM 22000 |
---|
51 | #define LINEDEPTH (int)12 |
---|
52 | #define PAGELINES (int)(260 / 12) |
---|
53 | #define TEXT 0 |
---|
54 | #define GFX 1 |
---|
55 | |
---|
56 | /* Global variables, most for use with input/output */ |
---|
57 | int disablescrollback = 0; |
---|
58 | int mode = TEXT; |
---|
59 | WindowPtr gfxWindow; |
---|
60 | WindowPtr textWindow; |
---|
61 | MenuHandle appleMenu,fileMenu; |
---|
62 | char *lines[SCROLLLINES]; /* the scrollback buffer */ |
---|
63 | int cursorx=0; /* the current x position that the text cursor is at */ |
---|
64 | int cursory=0; /* the current y position that the text cursor is at */ |
---|
65 | int numlines_=0;/* the next place we put a new line. */ |
---|
66 | int memptr=0; /* the next place in our space we get memory from. */ |
---|
67 | int linectr=0; |
---|
68 | char memory[SCROLLMEM]; |
---|
69 | char line[256];/* used to accumulate output before newlines. */ |
---|
70 | Rect textBounds = {40,5,300,500}; /* position of window 1 */ |
---|
71 | Rect gfxBounds = {0,0,350,500}; /* position of window 2 */ |
---|
72 | Rect textrect = {0,0,260,479}; /* region to clear within window */ |
---|
73 | Rect barBounds = {0,480,260,495}; /* position of the scroll bar */ |
---|
74 | RgnHandle rgn; /* used by scrollrect */ |
---|
75 | ControlHandle bar; /* this is the scrollbar control */ |
---|
76 | int lasttop=0; /* used by update / scrollrect */ |
---|
77 | char inputs[256]; /* used by the input routines */ |
---|
78 | int inputcount = 0; /* offset into the string. */ |
---|
79 | int collect = false; /* boolean: collect chars? */ |
---|
80 | |
---|
81 | void macsetup(tname,gname) |
---|
82 | char *tname,*gname; |
---|
83 | { |
---|
84 | static char buf1[128]; |
---|
85 | static char buf2[128]; |
---|
86 | |
---|
87 | strcpy(buf1+1,tname); |
---|
88 | strcpy(buf2+1,gname); |
---|
89 | buf1[0]=strlen(tname); |
---|
90 | buf2[0]=strlen(gname); |
---|
91 | MaxApplZone(); |
---|
92 | InitGraf(&thePort); |
---|
93 | InitFonts(); |
---|
94 | FlushEvents(everyEvent,0); |
---|
95 | InitWindows(); |
---|
96 | InitMenus(); |
---|
97 | TEInit(); |
---|
98 | InitDialogs(0L); |
---|
99 | InitCursor(); |
---|
100 | textWindow = NewWindow(0L,&textBounds,buf1,true,documentProc, |
---|
101 | (WindowPtr) -1L, true,0); |
---|
102 | gfxWindow = NewWindow(0L,&gfxBounds,buf2,false,noGrowDocProc, |
---|
103 | (WindowPtr) -1L, true,0); |
---|
104 | rgn=NewRgn(); |
---|
105 | SetPort(textWindow); |
---|
106 | bar=NewControl(textWindow,&barBounds,"",true,0,0, |
---|
107 | 0,scrollBarProc,0); |
---|
108 | InsertMenu(appleMenu=NewMenu(1,"\p\024"),0); /* add apple menu */ |
---|
109 | InsertMenu(fileMenu=NewMenu(2,"\pFile"),0); /* add file menu */ |
---|
110 | TextFont(courier); |
---|
111 | TextSize(10); |
---|
112 | DrawMenuBar(); |
---|
113 | AppendMenu(fileMenu,"\pQuit/Q"); |
---|
114 | AddResMenu(appleMenu, 'DRVR'); |
---|
115 | macprintf("\n"); |
---|
116 | } |
---|
117 | |
---|
118 | |
---|
119 | void queryevent() |
---|
120 | { |
---|
121 | int status; |
---|
122 | status=handleevent(); |
---|
123 | if (status <= 0) |
---|
124 | process_window_closure(status); |
---|
125 | } |
---|
126 | |
---|
127 | void eventloop() |
---|
128 | { |
---|
129 | int status; |
---|
130 | |
---|
131 | while (1){ |
---|
132 | status=handleevent(); |
---|
133 | if (status <= 0) |
---|
134 | process_window_closure(status); } |
---|
135 | } |
---|
136 | |
---|
137 | |
---|
138 | process_window_closure(status) |
---|
139 | int status; |
---|
140 | { |
---|
141 | if (status == -1){ |
---|
142 | CloseWindow(gfxWindow); /* "Close main window", so run all the */ |
---|
143 | CloseWindow(textWindow); /* cleanup stuff. */ |
---|
144 | DisposeRgn(rgn); |
---|
145 | #undef exit |
---|
146 | exit(0); |
---|
147 | #define exit(status) eventloop() |
---|
148 | } |
---|
149 | else if (status == 0) |
---|
150 | HideWindow(gfxWindow);} |
---|
151 | |
---|
152 | |
---|
153 | |
---|
154 | int handleevent() |
---|
155 | { |
---|
156 | pascal void scroll(); |
---|
157 | char pstring[256]; |
---|
158 | OSErr res; |
---|
159 | EventRecord ev; |
---|
160 | WindowPtr win; |
---|
161 | ControlHandle ctrl; |
---|
162 | short menuid,menuitem; |
---|
163 | Point MouseLoc; |
---|
164 | long menu,i; |
---|
165 | int cx,cy; |
---|
166 | int PathRefNum; |
---|
167 | long count=80; |
---|
168 | SFReply fileinfo; |
---|
169 | char c,pasteword[64]; |
---|
170 | Str255 name; |
---|
171 | GrafPtr savePort; |
---|
172 | FILE *fp; |
---|
173 | Rect drect; |
---|
174 | Rect rect = {0,0,1000,1000}; /* the limit for dragging windows */ |
---|
175 | int ok=GetNextEvent(everyEvent,&ev); |
---|
176 | int where=FindWindow(ev.where,&win); |
---|
177 | if (ev.what == keyDown && collect && mode != GFX){ |
---|
178 | SetCtlValue(bar,GetCtlMax(bar)); |
---|
179 | redraw(numlines_ - (GetCtlMax(bar) - GetCtlValue(bar)) - PAGELINES); |
---|
180 | } |
---|
181 | if ((ev.what == keyDown) && |
---|
182 | (ev.modifiers & cmdKey) && |
---|
183 | (toupper((char)(ev.message & charCodeMask)) == 'Q') ) |
---|
184 | return -1; |
---|
185 | if (( ev.what == keyDown ) && collect && mode == GFX){ |
---|
186 | textmode(); |
---|
187 | process_char((char)(ev.message & charCodeMask));} |
---|
188 | if (ev.what == mouseDown && !disablescrollback && where ==inContent & mode == TEXT){ |
---|
189 | SelectWindow(win); |
---|
190 | GlobalToLocal(&ev.where); |
---|
191 | switch (FindControl(ev.where,win,&ctrl)){ |
---|
192 | case inThumb: |
---|
193 | TrackControl(ctrl,ev.where,nil); |
---|
194 | break; |
---|
195 | case inUpButton: |
---|
196 | TrackControl(ctrl,ev.where,scroll); |
---|
197 | break; |
---|
198 | case inPageUp: |
---|
199 | SetCtlValue(bar,GetCtlValue(bar) - 10); |
---|
200 | break; |
---|
201 | case inDownButton: |
---|
202 | TrackControl(ctrl,ev.where,scroll); |
---|
203 | break; |
---|
204 | case inPageDown: |
---|
205 | SetCtlValue(bar,GetCtlValue(bar) + 10); |
---|
206 | break; |
---|
207 | default: |
---|
208 | if (collect && mode == TEXT){ |
---|
209 | GetMouse(&MouseLoc); |
---|
210 | cy = (int)((double)MouseLoc.v / (double)(LINEDEPTH)) + |
---|
211 | (numlines_ - (GetCtlMax(bar) - GetCtlValue(bar)) |
---|
212 | - PAGELINES + 1); |
---|
213 | for (i=0;i<strlen(lines[cy%SCROLLLINES]);++i) |
---|
214 | if ((lines[cy%SCROLLLINES])[i] == '(' || |
---|
215 | (lines[cy%SCROLLLINES])[i] == '(' ) |
---|
216 | (lines[cy%SCROLLLINES])[i]=' '; |
---|
217 | sscanf(lines[cy%SCROLLLINES]," %[0-9a-zA-Z]",pasteword); |
---|
218 | SetCtlValue(bar,GetCtlMax(bar)); |
---|
219 | redraw(numlines_ - (GetCtlMax(bar) - GetCtlValue(bar)) - PAGELINES); |
---|
220 | for (i=0;i<strlen(pasteword);++i) |
---|
221 | process_char(pasteword[i]); |
---|
222 | process_char(0x0d); |
---|
223 | } |
---|
224 | |
---|
225 | break; |
---|
226 | } |
---|
227 | redraw(numlines_ - (GetCtlMax(bar) - GetCtlValue(bar)) - PAGELINES); |
---|
228 | if (GetCtlMax(bar) == GetCtlValue(bar)){ |
---|
229 | macflush(); |
---|
230 | numlines_--;} |
---|
231 | } |
---|
232 | |
---|
233 | else if (ev.what == activateEvt) |
---|
234 | InvalRect(&win->portRect); |
---|
235 | else if (ev.what == updateEvt && mode == TEXT){ |
---|
236 | BeginUpdate(textWindow); |
---|
237 | lasttop=100000; |
---|
238 | redraw(numlines_ - (GetCtlMax(bar) - GetCtlValue(bar)) - PAGELINES); |
---|
239 | DrawControls(textWindow); |
---|
240 | EndUpdate(textWindow); |
---|
241 | } |
---|
242 | |
---|
243 | else if (ev.what == mouseDown && where == inSysWindow) |
---|
244 | SystemClick(&ev,win); |
---|
245 | else if (ev.what == mouseDown && where == inDrag) { |
---|
246 | DragWindow(win,ev.where,&rect);} |
---|
247 | |
---|
248 | else if (ev.what == mouseDown && where == inGoAway) |
---|
249 | return (win == gfxWindow ? 1: -1); |
---|
250 | |
---|
251 | if (ev.what == mouseDown && where == inMenuBar){ |
---|
252 | menu=MenuSelect(ev.where); |
---|
253 | menuitem = LoWord(menu); |
---|
254 | menuid = HiWord(menu); |
---|
255 | if (menuid == 2 && menuitem == 1) |
---|
256 | return -1; |
---|
257 | if (menuid == 1){ |
---|
258 | GetPort(&savePort); |
---|
259 | GetItem(appleMenu, menuitem, name); |
---|
260 | OpenDeskAcc(name); |
---|
261 | SetPort(savePort);} |
---|
262 | |
---|
263 | } |
---|
264 | else if (collect && mode == TEXT && (ev.what == keyDown)) |
---|
265 | process_char((char)(ev.message & charCodeMask)); |
---|
266 | |
---|
267 | return 1; |
---|
268 | } |
---|
269 | |
---|
270 | |
---|
271 | void macgets(s) |
---|
272 | char *s; |
---|
273 | { |
---|
274 | int status; |
---|
275 | collect=true; |
---|
276 | if (mode == GFX){ |
---|
277 | do {status=handleevent();} /* loop until this is false, or hit cr */ |
---|
278 | while (collect && status); |
---|
279 | |
---|
280 | if (status<= 0) process_window_closure(status); |
---|
281 | |
---|
282 | } |
---|
283 | |
---|
284 | else { |
---|
285 | macflush(); /* flush any waiting output (prompt?) */ |
---|
286 | numlines_--; |
---|
287 | inputcount=0; |
---|
288 | collect=true; /* tell the event loop to colect chars */ |
---|
289 | do {status=handleevent();} /* loop until this is false, or hit cr */ |
---|
290 | while (collect&&(status>0)); |
---|
291 | if (status<= 0) process_window_closure(status); |
---|
292 | inputs[inputcount]=0; |
---|
293 | strcpy(s,inputs); |
---|
294 | macprintf("\n"); |
---|
295 | } |
---|
296 | } |
---|
297 | |
---|
298 | int macscanf(char *s,...) |
---|
299 | { |
---|
300 | int i; |
---|
301 | char buf[256]; |
---|
302 | void *p[10]; |
---|
303 | va_list args; |
---|
304 | gets(buf); |
---|
305 | |
---|
306 | va_start(args,s); |
---|
307 | for (i=0;i<10;++i) |
---|
308 | p[i]=va_arg(args,void *); |
---|
309 | va_end(args); |
---|
310 | return sscanf(buf,s,p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9]); |
---|
311 | } |
---|
312 | |
---|
313 | void macputs(s) |
---|
314 | char *s; |
---|
315 | { |
---|
316 | macprintf("%s\n",s); |
---|
317 | } |
---|
318 | |
---|
319 | macputchar(c) |
---|
320 | char c; |
---|
321 | { |
---|
322 | macprintf("%c",c); |
---|
323 | } |
---|
324 | |
---|
325 | void macprintf(char *s,...) |
---|
326 | { |
---|
327 | char buf[256]; |
---|
328 | |
---|
329 | va_list args; |
---|
330 | int i; |
---|
331 | if (mode == GFX) |
---|
332 | return; |
---|
333 | if (strcmp(s,"\033[2J\033[H") ==0) |
---|
334 | return; |
---|
335 | disablescrollback=1; |
---|
336 | va_start(args,s); |
---|
337 | vsprintf(buf,s,args); |
---|
338 | va_end(args); |
---|
339 | queryevent(); |
---|
340 | SetPort(textWindow); |
---|
341 | MoveTo(cursorx,cursory); |
---|
342 | for (i=0;i<strlen(buf);++i){ |
---|
343 | if (isprint(buf[i])) |
---|
344 | line[linectr++]=buf[i]; |
---|
345 | else if (buf[i] == '\n'){ |
---|
346 | macflush(); |
---|
347 | linectr=0; |
---|
348 | macnewline(); |
---|
349 | } |
---|
350 | } |
---|
351 | disablescrollback=0; |
---|
352 | } |
---|
353 | |
---|
354 | macflush() |
---|
355 | { |
---|
356 | line[linectr]=0; |
---|
357 | if ((memptr+strlen(line) +1) > SCROLLMEM) |
---|
358 | memptr=0; |
---|
359 | |
---|
360 | lines[(numlines_)%SCROLLLINES]=&memory[(numlines_%SCROLLLINES)*SCROLLCOLUMNS]; |
---|
361 | strcpy(lines[(numlines_++)%SCROLLLINES],line); |
---|
362 | MoveTo(0,cursory); |
---|
363 | putstring(line); |
---|
364 | } |
---|
365 | |
---|
366 | macclear() |
---|
367 | { |
---|
368 | cursorx=0; |
---|
369 | cursory=0; |
---|
370 | EraseRect(&textrect); |
---|
371 | } |
---|
372 | |
---|
373 | macnewline() |
---|
374 | { |
---|
375 | int i; |
---|
376 | cursorx=0; |
---|
377 | cursory+=LINEDEPTH; |
---|
378 | if (cursory > 260 ){ |
---|
379 | cursory-=LINEDEPTH;} |
---|
380 | MoveTo(cursorx,cursory); |
---|
381 | SetCtlMax(bar,((numlines_ > SCROLLLINES ) ? SCROLLLINES : |
---|
382 | (numlines_ )) - PAGELINES); |
---|
383 | SetCtlValue(bar,GetCtlMax(bar)); |
---|
384 | redraw(numlines_ - (GetCtlMax(bar) - GetCtlValue(bar)) - PAGELINES); |
---|
385 | |
---|
386 | } |
---|
387 | |
---|
388 | |
---|
389 | redraw(pos) |
---|
390 | int pos; |
---|
391 | { |
---|
392 | int i,j,y=0; |
---|
393 | int lastbot = lasttop+pos; |
---|
394 | int delta = pos-lasttop; |
---|
395 | int delta2 = lasttop-pos; |
---|
396 | int lbound = pos; |
---|
397 | int ubound = pos+PAGELINES; |
---|
398 | int tmpx = cursorx; |
---|
399 | int tmpy = cursory; |
---|
400 | if (numlines_ < PAGELINES) |
---|
401 | delta=delta2=10000; |
---|
402 | textmode(); |
---|
403 | pos = (pos < 0 ? 0 : pos); |
---|
404 | if (delta >= 0 && delta < SCROLLLINES ){ |
---|
405 | ScrollRect(&textrect,0,-delta*LINEDEPTH,rgn); |
---|
406 | lbound = pos+PAGELINES-delta; |
---|
407 | } |
---|
408 | else if (delta2 > 0 && delta2 < SCROLLLINES ){ |
---|
409 | ScrollRect(&textrect,0,delta2*LINEDEPTH,rgn); |
---|
410 | ubound=delta2+pos; |
---|
411 | |
---|
412 | } |
---|
413 | |
---|
414 | else if (numlines_ >= PAGELINES) |
---|
415 | EraseRect(&textrect); |
---|
416 | if (numlines_ == ubound) |
---|
417 | ubound--; |
---|
418 | for (i=pos;i<pos-1+((PAGELINES < numlines_) ? numlines_ : PAGELINES);++i){ |
---|
419 | MoveTo(0,y); |
---|
420 | if (i>= lbound && i<= ubound) |
---|
421 | putstring(lines[i%SCROLLLINES]); |
---|
422 | y+=LINEDEPTH; |
---|
423 | |
---|
424 | } |
---|
425 | MoveTo(0,y); |
---|
426 | y+=LINEDEPTH; |
---|
427 | lasttop = pos; |
---|
428 | MoveTo(tmpx,tmpy); |
---|
429 | } |
---|
430 | |
---|
431 | putstring(string) |
---|
432 | char *string; |
---|
433 | { |
---|
434 | char buf[256]; |
---|
435 | strcpy(buf+1,string); |
---|
436 | buf[0]=strlen(string); |
---|
437 | DrawString(buf); |
---|
438 | cursorx+=StringWidth(buf); |
---|
439 | } |
---|
440 | |
---|
441 | textmode() |
---|
442 | { |
---|
443 | SetPort(textWindow); |
---|
444 | SelectWindow(textWindow); |
---|
445 | ShowWindow(textWindow); |
---|
446 | HideWindow(gfxWindow); |
---|
447 | mode = TEXT; |
---|
448 | } |
---|
449 | |
---|
450 | gfxmode() |
---|
451 | { |
---|
452 | int status,ok; |
---|
453 | EventRecord ev; |
---|
454 | char c; |
---|
455 | |
---|
456 | SetPort(gfxWindow); |
---|
457 | ShowWindow(gfxWindow); |
---|
458 | HideWindow(textWindow); |
---|
459 | SelectWindow(gfxWindow); |
---|
460 | mode = GFX; |
---|
461 | } |
---|
462 | |
---|
463 | pascal void scroll(c,p) |
---|
464 | ControlHandle c; |
---|
465 | int p; |
---|
466 | { |
---|
467 | int direction=((p == inDownButton) ? 1 : (p == 0) ? 0 : -1); |
---|
468 | SetCtlValue(bar,GetCtlValue(bar) + direction); |
---|
469 | /* redraw(numlines_ - (GetCtlMax(bar) - GetCtlValue(bar)) - PAGELINES); |
---|
470 | */ |
---|
471 | } |
---|
472 | |
---|
473 | process_char(c) |
---|
474 | char c; |
---|
475 | { |
---|
476 | Rect drect; |
---|
477 | |
---|
478 | if (isprint(c)){ |
---|
479 | inputs[inputcount++]=c; |
---|
480 | line[linectr++]=c; |
---|
481 | if (GetCtlValue(bar) == GetCtlMax(bar) && mode==TEXT) { |
---|
482 | macflush(); |
---|
483 | numlines_--;} |
---|
484 | } |
---|
485 | else{ |
---|
486 | switch (c){ |
---|
487 | case 0x03: /* if it's the enter key */ |
---|
488 | case 0x0d: /* or the return key */ |
---|
489 | collect=false; /* stop collecting chars */ |
---|
490 | break; |
---|
491 | case 0x08: /* delete */ |
---|
492 | case 0x1c: /* or back space */ |
---|
493 | if (inputcount > 0 && mode == TEXT) { |
---|
494 | cursorx-=CharWidth(inputs[--inputcount]); |
---|
495 | MoveTo(cursorx,cursory); |
---|
496 | inputs[inputcount]=0; |
---|
497 | drect.top=cursory-LINEDEPTH; |
---|
498 | drect.left=0; |
---|
499 | drect.bottom=cursory+3; |
---|
500 | drect.right=344; |
---|
501 | EraseRect(&drect); |
---|
502 | line[--linectr]=0; |
---|
503 | if (GetCtlValue(bar) == GetCtlMax(bar)){ |
---|
504 | macflush(); |
---|
505 | numlines_--;} |
---|
506 | } |
---|
507 | break; |
---|
508 | default: |
---|
509 | break;} |
---|
510 | } |
---|
511 | } |
---|
512 | |
---|
513 | void fixmacfile(filename) |
---|
514 | char *filename; |
---|
515 | { |
---|
516 | OSErr retcode; |
---|
517 | FInfo fndrinfo; |
---|
518 | char filename1[100]; |
---|
519 | char filename2[100]; |
---|
520 | strcpy(filename1,filename); |
---|
521 | strcpy(filename2,filename); |
---|
522 | retcode=GetFInfo(CtoPstr(filename1),0,&fndrinfo); |
---|
523 | fndrinfo.fdType='TEXT'; |
---|
524 | fndrinfo.fdCreator='MSWD'; |
---|
525 | retcode=SetFInfo(CtoPstr(filename2),0,&fndrinfo); |
---|
526 | } |
---|
527 | |
---|