1/* 2** interpret.c 3** 4** interprets and executes lines in the Xgc syntax. 5*/ 6 7#include <stdio.h> 8#include <stdlib.h> 9#include <X11/Intrinsic.h> 10#include <X11/StringDefs.h> 11#include "xgc.h" 12#include "tile" 13 14 15/* interpret(string) 16** ----------------- 17** Takes string, which is a line written in the xgc syntax, figures 18** out what it means, and passes the buck to the right procedure. 19** That procedure gets called with feedback set to FALSE; interpret() 20** is only called if the user is selecting things interactively. 21** 22** This procedure will go away when I can figure out how to make yacc 23** and lex read from strings as well as files. 24*/ 25 26void 27interpret(const char *string) 28{ 29 char word1[20], word2[80]; 30 int i; 31 32 sscanf(string,"%s",word1); 33 if (!strcmp(word1,"run")) run_test(); 34 35 else { 36 sscanf(string,"%s %s",word1,word2); 37 print_if_recording(string); 38 39 /* So word1 is the first word on the line and word2 is the second. 40 Now the fun begins... */ 41 42 if (!strcmp(word1,TestStuff.choice.text)) { 43 for (i=0;i<NUM_TESTS;++i) { 44 if (!strcmp(word2,(TestStuff.data)[i].text)) { 45 change_test((TestStuff.data)[i].code,FALSE); 46 break; 47 } 48 } 49 } 50 else if (!strcmp(word1,FunctionStuff.choice.text)) { 51 for (i=0;i<NUM_FUNCTIONS;++i) { 52 if (!strcmp(word2,(FunctionStuff.data)[i].text)) { 53 GC_change_function((FunctionStuff.data)[i].code,FALSE); 54 break; 55 } 56 } 57 } 58 else if (!strcmp(word1,LinestyleStuff.choice.text)) { 59 for (i=0;i<NUM_LINESTYLES;++i) { 60 if (!strcmp(word2,(LinestyleStuff.data)[i].text)) { 61 GC_change_linestyle((LinestyleStuff.data)[i].code,FALSE); 62 break; 63 } 64 } 65 } 66 else if (!strcmp(word1,"linewidth")) 67 GC_change_linewidth(atoi(word2),FALSE); 68 else if (!strcmp(word1,CapstyleStuff.choice.text)) { 69 for (i=0;i<NUM_CAPSTYLES;++i) { 70 if (!strcmp(word2,(CapstyleStuff.data)[i].text)) { 71 GC_change_capstyle((CapstyleStuff.data)[i].code,FALSE); 72 break; 73 } 74 } 75 } 76 else if (!strcmp(word1,JoinstyleStuff.choice.text)) { 77 for (i=0;i<NUM_JOINSTYLES;++i) { 78 if (!strcmp(word2,(JoinstyleStuff.data)[i].text)) { 79 GC_change_joinstyle((JoinstyleStuff.data)[i].code,FALSE); 80 break; 81 } 82 } 83 } 84 else if (!strcmp(word1,FillstyleStuff.choice.text)) { 85 for (i=0;i<NUM_FILLSTYLES;++i) { 86 if (!strcmp(word2,(FillstyleStuff.data)[i].text)) { 87 GC_change_fillstyle((FillstyleStuff.data)[i].code,FALSE); 88 break; 89 } 90 } 91 } 92 else if (!strcmp(word1,FillruleStuff.choice.text)) { 93 for (i=0;i<NUM_FILLRULES;++i) { 94 if (!strcmp(word2,(FillruleStuff.data)[i].text)) { 95 GC_change_fillrule((FillruleStuff.data)[i].code,FALSE); 96 break; 97 } 98 } 99 } 100 else if (!strcmp(word1,ArcmodeStuff.choice.text)) { 101 for (i=0;i<NUM_ARCMODES;++i) { 102 if (!strcmp(word2,(ArcmodeStuff.data)[i].text)) { 103 GC_change_arcmode((ArcmodeStuff.data)[i].code,FALSE); 104 break; 105 } 106 } 107 } 108 else if (!strcmp(word1,"planemask")) 109 GC_change_planemask((unsigned long) atoi(word2),FALSE); 110 else if (!strcmp(word1,"dashlist")) 111 GC_change_dashlist(atoi(word2),FALSE); 112 else if (!strcmp(word1,"font")) 113 GC_change_font(word2,FALSE); 114 else if (!strcmp(word1,"foreground")) 115 GC_change_foreground((unsigned long) atoi(word2),FALSE); 116 else if (!strcmp(word1,"background")) 117 GC_change_background((unsigned long) atoi(word2),FALSE); 118 else if (!strcmp(word1,"percent")) 119 change_percent(atoi(word2), FALSE); 120 else fprintf(stderr,"Ack... %s %s\n",word1,word2); 121 } 122} 123 124#ifdef notdef 125void 126interpret(const char *instring) 127{ 128 FILE *inend; 129 130 print_if_recording(instring); 131 yyin = outend; 132 inend = fdopen(fildes[1],"w"); 133 fprintf(inend,"%s",instring); 134 fclose(inend); 135 yyparse(); 136} 137#endif 138 139#define select_correct_button(which,number) \ 140 select_button(GCdescs[(which)],(number)); 141 142/* GC_change_blahzee(foo,feedback) 143** --------------------- 144** Changes the blahzee field in xgc's GC to foo. If feedback is TRUE, 145** changes the display to reflect this (makes it look like the user 146** selected the button, or typed in the text, or whatever). 147*/ 148 149void 150GC_change_function(int function, Boolean feedback) 151{ 152 XSetFunction(X.dpy,X.gc,function); 153 X.gcv.function = function; 154 if (feedback) select_correct_button(CFunction,function); 155} 156 157void 158GC_change_foreground(unsigned long foreground, Boolean feedback) 159{ 160 char text[40]; 161 162 XSetForeground(X.dpy,X.miscgc,foreground); 163 XCopyPlane(X.dpy,X.stipple,X.tile,X.miscgc,0,0,tile_width,tile_height,0,0,1); 164 XSetForeground(X.dpy,X.gc,foreground); 165 X.gcv.foreground = foreground; 166 XSetTile(X.dpy,X.gc,X.tile); 167 XSetTile(X.dpy,X.miscgc,X.tile); 168 if (feedback) { 169 snprintf(text, sizeof text, "%lu",foreground); 170 change_text(foregroundtext,text); 171 } 172} 173 174void 175GC_change_background(unsigned long background, Boolean feedback) 176{ 177 char text[40]; 178 179 XSetBackground(X.dpy,X.miscgc,background); 180 XCopyPlane(X.dpy,X.stipple,X.tile,X.miscgc,0,0,tile_width,tile_height,0,0,1); 181 XSetBackground(X.dpy,X.gc,background); 182 X.gcv.background = background; 183 XSetTile(X.dpy,X.gc,X.tile); 184 XSetTile(X.dpy,X.miscgc,X.tile); 185 186 /* Update the background of the test window NOW. */ 187 188 XSetWindowBackground(X.dpy,XtWindow(test),background); 189 XClearWindow(X.dpy,XtWindow(test)); 190 191 if (feedback) { 192 snprintf(text, sizeof text, "%lu",background); 193 change_text(backgroundtext,text); 194 } 195} 196 197void 198GC_change_linewidth(int linewidth, Boolean feedback) 199{ 200 char text[40]; 201 202 X.gcv.line_width = linewidth; 203 XChangeGC(X.dpy,X.gc,GCLineWidth,&X.gcv); 204 if (feedback) { 205 snprintf(text, sizeof text, "%d",linewidth); 206 change_text(linewidthtext,text); 207 } 208} 209 210void 211GC_change_linestyle(int linestyle, Boolean feedback) 212{ 213 X.gcv.line_style = linestyle; 214 XChangeGC(X.dpy,X.gc,GCLineStyle,&X.gcv); 215 if (feedback) select_correct_button(CLinestyle,linestyle); 216} 217 218void 219GC_change_capstyle(int capstyle, Boolean feedback) 220{ 221 X.gcv.cap_style = capstyle; 222 XChangeGC(X.dpy,X.gc,GCCapStyle,&X.gcv); 223 if (feedback) select_correct_button(CCapstyle,capstyle); 224} 225 226void 227GC_change_joinstyle(int joinstyle, Boolean feedback) 228{ 229 X.gcv.join_style = joinstyle; 230 XChangeGC(X.dpy,X.gc,GCJoinStyle,&X.gcv); 231 if (feedback) select_correct_button(CJoinstyle,joinstyle); 232} 233 234void 235GC_change_fillstyle(int fillstyle, Boolean feedback) 236{ 237 XSetFillStyle(X.dpy,X.gc,fillstyle); 238 X.gcv.fill_style = fillstyle; 239 if (feedback) select_correct_button(CFillstyle,fillstyle); 240} 241 242void 243GC_change_fillrule(int fillrule, Boolean feedback) 244{ 245 XSetFillRule(X.dpy,X.gc,fillrule); 246 X.gcv.fill_rule = fillrule; 247 if (feedback) select_correct_button(CFillrule,fillrule); 248} 249 250void 251GC_change_arcmode(int arcmode, Boolean feedback) 252{ 253 XSetArcMode(X.dpy,X.gc,arcmode); 254 X.gcv.arc_mode = arcmode; 255 if (feedback) select_correct_button(CArcmode,arcmode); 256} 257 258/* GC_change_dashlist(dashlist) 259** ---------------------------- 260** Now this one's a bit tricky. dashlist gets passed in as an int, but we 261** want to change it to an array of chars, like the GC likes it. 262** For example: 263** 119 => XXX_XXX_ => [3,1,3,1] 264*/ 265 266void 267GC_change_dashlist(int dashlist, Boolean feedback) 268{ 269 char dasharray[DASHLENGTH]; /* what we're going to pass to XSetDashes */ 270 int dashnumber = 0; /* which element of dasharray we're currently 271 modifying */ 272 int i; /* which bit of the dashlist we're on */ 273 int state = 1; /* whether the list bit we checked was 274 on (1) or off (0) */ 275 276 /* Initialize the dasharray */ 277 278 for (i = 0; i < DASHLENGTH; ++i) dasharray[i] = 0; 279 280 if (dashlist == 0) return; /* having no dashes at all is bogus */ 281 282 /* XSetDashes expects the dashlist to start with an on bit, so if it 283 ** doesn't, we keep on rotating it until it does */ 284 285 while (!(dashlist&1)) dashlist /= 2; 286 287 /* Go through all the bits in dashlist, and update the dasharray 288 ** accordingly */ 289 290 for (i = 0; i < DASHLENGTH; ++i) { 291 /* the following if statements checks to see if the bit we're looking 292 ** at as the same on or offness as the one before it (state). If 293 ** so, we increment the length of the current dash. */ 294 295 if (((dashlist&1<<i) && state) || (!(dashlist&1<<i) && !state)) 296 ++dasharray[dashnumber]; 297 else { 298 state = state^1; /* reverse the state */ 299 ++dasharray[++dashnumber]; /* start a new dash */ 300 } 301 } 302 303 XSetDashes(X.dpy,X.gc,0,dasharray,dashnumber+1); 304 X.gcv.dashes = dashlist; 305 306 if (feedback) update_dashlist(dashlist); 307} 308 309void 310GC_change_planemask(unsigned long planemask, Boolean feedback) 311{ 312 XSetPlaneMask(X.dpy,X.gc,planemask); 313 X.gcv.plane_mask = planemask; 314 if (feedback) update_planemask((long)planemask); 315} 316 317void 318change_test(int test, Boolean feedback) 319{ 320 X.test = test; 321 if (feedback) select_button(testchoicedesc,test); 322} 323 324void 325GC_change_font(char *str, Boolean feedback) 326{ 327 int num_fonts; /* number of fonts that match the string */ 328 329 XListFonts(X.dpy,str,1,&num_fonts); /* see if the font exists */ 330 331 if (num_fonts) { 332 XSetFont(X.dpy,X.gc,XLoadFont(X.dpy,str)); 333 if (feedback) change_text(fonttext,str); 334 } 335} 336 337void 338change_percent(int percent, Boolean feedback) 339{ 340 /* Make sure that percent is valid */ 341 342 if (percent < 1 || percent > 100) return; 343 344 X.percent = (float) percent / 100.0; 345 346 if (feedback) update_slider(percent); 347} 348