00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "RConfigure.h"
00014
00015 #include <stdio.h>
00016 #include <unistd.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <pwd.h>
00020 #include <sys/types.h>
00021 #include <X11/Xlib.h>
00022 #include <X11/xpm.h>
00023
00024 #include "Rtypes.h"
00025
00026 #if defined(R__AIX) || defined(R__SOLARIS)
00027 # include <sys/select.h>
00028 #endif
00029 #include <time.h>
00030 #include <sys/time.h>
00031
00032 static Display *gDisplay = 0;
00033 static Window gLogoWindow = 0;
00034 static Pixmap gLogoPixmap = 0;
00035 static Pixmap gCreditsPixmap = 0;
00036 static GC gGC = 0;
00037 static XFontStruct *gFont = 0;
00038 static bool gDone = false;
00039 static bool gMayPopdown = false;
00040 static bool gAbout = false;
00041 static unsigned int gWidth = 0;
00042 static unsigned int gHeight = 0;
00043 static int gStayUp = 4000;
00044 static XRectangle gCreditsRect = { 15, 155, 285, 130 };
00045 static unsigned int gCreditsWidth = gCreditsRect.width;
00046 static unsigned int gCreditsHeight = 0;
00047
00048 static struct timeval gPopupTime;
00049
00050 static const char *gConception[] = {
00051 "Rene Brun",
00052 "Fons Rademakers",
00053 0
00054 };
00055
00056 static const char *gLeadDevelopers[] = {
00057 "Rene Brun",
00058 "Philippe Canal",
00059 "Fons Rademakers",
00060 0
00061 };
00062
00063 static const char *gRootDevelopers[] = {
00064 "Bertrand Bellenot",
00065 "Olivier Couet",
00066 "Gerardo Ganis",
00067 "Andrei Gheata",
00068 "Lorenzo Moneta",
00069 "Axel Naumann",
00070 "Paul Russo",
00071 "Matevz Tadel",
00072 0
00073 };
00074
00075 static const char *gCintDevelopers[] = {
00076 "Masaharu Goto",
00077 0
00078 };
00079
00080 static const char *gRootDocumentation[] = {
00081 "Ilka Antcheva",
00082 0
00083 };
00084
00085 static char **gContributors = 0;
00086
00087
00088
00089 static bool StayUp(int milliSec)
00090 {
00091
00092
00093
00094 struct timeval ctv, dtv, tv, ptv = gPopupTime;
00095
00096 tv.tv_sec = milliSec / 1000;
00097 tv.tv_usec = (milliSec % 1000) * 1000;
00098
00099 gettimeofday(&ctv, 0);
00100 if ((dtv.tv_usec = ctv.tv_usec - ptv.tv_usec) < 0) {
00101 dtv.tv_usec += 1000000;
00102 ptv.tv_sec++;
00103 }
00104 dtv.tv_sec = ctv.tv_sec - ptv.tv_sec;
00105
00106 if ((ctv.tv_usec = tv.tv_usec - dtv.tv_usec) < 0) {
00107 ctv.tv_usec += 1000000;
00108 dtv.tv_sec++;
00109 }
00110 ctv.tv_sec = tv.tv_sec - dtv.tv_sec;
00111
00112 if (ctv.tv_sec < 0) return false;
00113
00114 return true;
00115 }
00116
00117 static void Sleep(int milliSec)
00118 {
00119
00120
00121
00122 struct timeval tv;
00123
00124 tv.tv_sec = milliSec / 1000;
00125 tv.tv_usec = (milliSec % 1000) * 1000;
00126
00127 select(0, 0, 0, 0, &tv);
00128 }
00129
00130 static Pixmap GetRootLogo()
00131 {
00132
00133
00134 Pixmap logo = 0;
00135 int depth = PlanesOfScreen(XDefaultScreenOfDisplay(gDisplay));
00136
00137 XWindowAttributes win_attr;
00138 XGetWindowAttributes(gDisplay, gLogoWindow, &win_attr);
00139
00140 XpmAttributes attr;
00141 attr.valuemask = XpmVisual | XpmColormap | XpmDepth;
00142 attr.visual = win_attr.visual;
00143 attr.colormap = win_attr.colormap;
00144 attr.depth = win_attr.depth;
00145
00146 #ifdef XpmColorKey // Not available in XPM 3.2 and earlier
00147 attr.valuemask |= XpmColorKey;
00148 if (depth > 4)
00149 attr.color_key = XPM_COLOR;
00150 else if (depth > 2)
00151 attr.color_key = XPM_GRAY4;
00152 else if (depth > 1)
00153 attr.color_key = XPM_GRAY;
00154 else if (depth == 1)
00155 attr.color_key = XPM_MONO;
00156 else
00157 attr.valuemask &= ~XpmColorKey;
00158
00159 #endif // defined(XpmColorKey)
00160
00161 char file[2048];
00162 #ifdef ROOTICONPATH
00163 snprintf(file, sizeof(file), "%s/Splash.xpm", ROOTICONPATH);
00164 #else
00165 snprintf(file, sizeof(file), "%s/icons/Splash.xpm", getenv("ROOTSYS"));
00166 #endif
00167 int ret = XpmReadFileToPixmap(gDisplay, gLogoWindow,
00168 file, &logo, 0, &attr);
00169 XpmFreeAttributes(&attr);
00170
00171 if (ret == XpmSuccess || ret == XpmColorError)
00172 return logo;
00173
00174 printf("rootx xpm error: %s\n", XpmGetErrorString(ret));
00175
00176 if (logo) XFreePixmap(gDisplay, logo);
00177 logo = 0;
00178
00179 return logo;
00180 }
00181
00182 static void ReadContributors()
00183 {
00184
00185
00186
00187 char buf[2048];
00188 #ifdef ROOTDOCDIR
00189 snprintf(buf, sizeof(buf), "%s/CREDITS", ROOTDOCDIR);
00190 #else
00191 snprintf(buf, sizeof(buf), "%s/README/CREDITS", getenv("ROOTSYS"));
00192 #endif
00193
00194 gContributors = 0;
00195
00196 FILE *f = fopen(buf, "r");
00197 if (!f) return;
00198
00199 int cnt = 0;
00200 while (fgets(buf, sizeof(buf), f)) {
00201 if (!strncmp(buf, "N: ", 3)) {
00202 cnt++;
00203 }
00204 }
00205 gContributors = new char*[cnt+1];
00206
00207 cnt = 0;
00208 rewind(f);
00209 while (fgets(buf, sizeof(buf), f)) {
00210 if (!strncmp(buf, "N: ", 3)) {
00211 int len = strlen(buf);
00212 buf[len-1] = 0;
00213 len -= 3;
00214 gContributors[cnt] = new char[len];
00215 strncpy(gContributors[cnt], buf+3, len);
00216 cnt++;
00217 }
00218 }
00219 gContributors[cnt] = 0;
00220
00221 fclose(f);
00222 }
00223
00224 static void DrawVersion()
00225 {
00226
00227
00228 char version[80];
00229 sprintf(version, "Version %s", ROOT_RELEASE);
00230
00231 XDrawString(gDisplay, gLogoWindow, gGC, 15, gHeight - 15, version,
00232 strlen(version));
00233 }
00234
00235 static int DrawCreditItem(const char *creditItem, const char **members,
00236 int y, bool draw)
00237 {
00238
00239
00240 char credit[1024];
00241 int i;
00242 int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent;
00243
00244 strlcpy(credit, creditItem, sizeof(credit));
00245 for (i = 0; members && members[i]; i++) {
00246 if (i) strcat(credit, ", ");
00247 if (XTextWidth(gFont, credit, strlen(credit)) +
00248 XTextWidth(gFont, members[i], strlen(members[i])) > (int) gCreditsWidth) {
00249 if (draw)
00250 XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit));
00251 y += lineSpacing;
00252 strcpy(credit, " ");
00253 }
00254 strcat(credit, members[i]);
00255 }
00256 if (draw)
00257 XDrawString(gDisplay, gCreditsPixmap, gGC, 0, y, credit, strlen(credit));
00258
00259 return y;
00260 }
00261
00262 static int DrawCredits(bool draw, bool extended)
00263 {
00264
00265
00266
00267
00268
00269 if (!gFont) return 150;
00270
00271 int lineSpacing = gFont->max_bounds.ascent + gFont->max_bounds.descent;
00272 int y = lineSpacing;
00273
00274 y = DrawCreditItem("Conception: ", gConception, y, draw);
00275
00276 y += 2*lineSpacing;
00277
00278 y = DrawCreditItem("Lead Developers: ", gLeadDevelopers, y, draw);
00279
00280 y += 2*lineSpacing - 1;
00281
00282 y = DrawCreditItem("Core Engineering: ", gRootDevelopers, y, draw);
00283
00284 y += 2*lineSpacing - 1;
00285
00286 y = DrawCreditItem("CINT C/C++ Intepreter: ", gCintDevelopers, y, draw);
00287
00288 y += 2*lineSpacing;
00289
00290 y = DrawCreditItem("Documentation: ", gRootDocumentation, y, draw);
00291
00292 if (extended && gContributors) {
00293 y += 2*lineSpacing;
00294 y = DrawCreditItem("Contributors: ", (const char **)gContributors, y, draw);
00295
00296 y += 2*lineSpacing;
00297 y = DrawCreditItem("Our sincere thanks and apologies to anyone who deserves", 0, y, draw);
00298 y += lineSpacing;
00299 y = DrawCreditItem("credit but fails to appear in this list.", 0, y, draw);
00300
00301 struct passwd *pwd = getpwuid(getuid());
00302 if (pwd) {
00303 char *name = new char [strlen(pwd->pw_gecos)+1];
00304 strcpy(name, pwd->pw_gecos);
00305 char *s = strchr(name, ',');
00306 if (s) *s = 0;
00307 char line[1024];
00308 if (strlen(name))
00309 snprintf(line, sizeof(line), "Extra special thanks go to %s,", name);
00310 else
00311 snprintf(line, sizeof(line), "Extra special thanks go to %s,", pwd->pw_name);
00312 delete [] name;
00313 y += 2*lineSpacing;
00314 y = DrawCreditItem(line, 0, y, draw);
00315 y += lineSpacing;
00316 y = DrawCreditItem("one of our favorite users.", 0, y, draw);
00317 }
00318 }
00319
00320 return y;
00321 }
00322
00323 void ScrollCredits(int ypos)
00324 {
00325 XRectangle crect[1];
00326 crect[0] = gCreditsRect;
00327 XSetClipRectangles(gDisplay, gGC, 0, 0, crect, 1, Unsorted);
00328
00329 XCopyArea(gDisplay, gCreditsPixmap, gLogoWindow, gGC,
00330 0, ypos, gCreditsWidth, gCreditsHeight, gCreditsRect.x, gCreditsRect.y);
00331
00332 XSetClipMask(gDisplay, gGC, None);
00333 }
00334
00335 void PopupLogo(bool about)
00336 {
00337
00338
00339 gDisplay = XOpenDisplay("");
00340 if (!gDisplay) return;
00341
00342 gAbout = about;
00343
00344 Pixel back, fore;
00345 int screen = DefaultScreen(gDisplay);
00346
00347 back = WhitePixel(gDisplay, screen);
00348 fore = BlackPixel(gDisplay, screen);
00349
00350 gLogoWindow = XCreateSimpleWindow(gDisplay, DefaultRootWindow(gDisplay),
00351 -100, -100, 50, 50, 0, fore, back);
00352
00353 gLogoPixmap = GetRootLogo();
00354 if (!gLogoPixmap) {
00355 XCloseDisplay(gDisplay);
00356 gDisplay = 0;
00357 return;
00358 }
00359
00360 Window root;
00361 int x, y;
00362 unsigned int bw, depth;
00363 XGetGeometry(gDisplay, gLogoPixmap, &root, &x, &y, &gWidth, &gHeight,
00364 &bw, &depth);
00365
00366 Screen *xscreen = XDefaultScreenOfDisplay(gDisplay);
00367 x = (WidthOfScreen(xscreen) - gWidth) / 2;
00368 y = (HeightOfScreen(xscreen) - gHeight) / 2;
00369
00370 XMoveResizeWindow(gDisplay, gLogoWindow, x, y, gWidth, gHeight);
00371 XSync(gDisplay, False);
00372
00373 unsigned long valmask;
00374 XSetWindowAttributes xswa;
00375 valmask = CWBackPixmap | CWOverrideRedirect;
00376 xswa.background_pixmap = gLogoPixmap;
00377 xswa.override_redirect = True;
00378 XChangeWindowAttributes(gDisplay, gLogoWindow, valmask, &xswa);
00379
00380 gGC = XCreateGC(gDisplay, gLogoWindow, 0, 0);
00381 gFont = XLoadQueryFont(gDisplay, "-adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-iso8859-1");
00382 if (!gFont) {
00383 printf("Couldn't find font \"-adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-iso8859-1\",\n"
00384 "trying \"fixed\". Please fix your system so helvetica can be found, \n"
00385 "this font typically is in the rpm (or pkg equivalent) package \n"
00386 "XFree86-[75,100]dpi-fonts or fonts-xorg-[75,100]dpi.\n");
00387 gFont = XLoadQueryFont(gDisplay, "fixed");
00388 if (!gFont)
00389 printf("Also couln't find font \"fixed\", your system is terminally misconfigured.\n");
00390 }
00391 if (gFont)
00392 XSetFont(gDisplay, gGC, gFont->fid);
00393 XSetForeground(gDisplay, gGC, fore);
00394 XSetBackground(gDisplay, gGC, back);
00395
00396 if (about)
00397 ReadContributors();
00398
00399 gCreditsHeight = DrawCredits(false, about) + gCreditsRect.height + 50;
00400 gCreditsPixmap = XCreatePixmap(gDisplay, gLogoWindow, gCreditsWidth, gCreditsHeight, depth);
00401 XSetForeground(gDisplay, gGC, back);
00402 XFillRectangle(gDisplay, gCreditsPixmap, gGC, 0, 0, gCreditsWidth, gCreditsHeight);
00403 XSetForeground(gDisplay, gGC, fore);
00404 DrawCredits(true, about);
00405
00406 XSelectInput(gDisplay, gLogoWindow, ButtonPressMask | ExposureMask);
00407
00408 XMapRaised(gDisplay, gLogoWindow);
00409
00410 gettimeofday(&gPopupTime, 0);
00411 }
00412
00413 void WaitLogo()
00414 {
00415
00416
00417
00418 if (!gDisplay) return;
00419
00420 int ypos = 0;
00421 bool stopScroll = false;
00422
00423 ScrollCredits(ypos);
00424 DrawVersion();
00425 XFlush(gDisplay);
00426
00427 while (!gDone) {
00428 XEvent event;
00429 if (XCheckMaskEvent(gDisplay, ButtonPressMask | ExposureMask, &event)) {
00430 switch (event.type) {
00431 case Expose:
00432 if (event.xexpose.count == 0) {
00433 ScrollCredits(ypos);
00434 DrawVersion();
00435 }
00436 break;
00437 case ButtonPress:
00438 if (gAbout && event.xbutton.button == 3)
00439 stopScroll = stopScroll ? false : true;
00440 else
00441 gDone = true;
00442 break;
00443 default:
00444 break;
00445 }
00446 }
00447
00448 Sleep(100);
00449
00450 if (!gAbout && !StayUp(gStayUp) && gMayPopdown)
00451 gDone = true;
00452
00453 if (gAbout && !stopScroll) {
00454 if (ypos == 0) Sleep(2000);
00455 ypos++;
00456 if (ypos > (int) (gCreditsHeight - gCreditsRect.height - 50))
00457 ypos = -int(gCreditsRect.height);
00458 ScrollCredits(ypos);
00459 XFlush(gDisplay);
00460 }
00461 }
00462
00463 if (gLogoWindow) {
00464 XUnmapWindow(gDisplay, gLogoWindow);
00465 XDestroyWindow(gDisplay, gLogoWindow);
00466 gLogoWindow = 0;
00467 }
00468 if (gLogoPixmap) {
00469 XFreePixmap(gDisplay, gLogoPixmap);
00470 gLogoPixmap = 0;
00471 }
00472 if (gCreditsPixmap) {
00473 XFreePixmap(gDisplay, gCreditsPixmap);
00474 gCreditsPixmap = 0;
00475 }
00476 if (gFont) {
00477 XFreeFont(gDisplay, gFont);
00478 gFont = 0;
00479 }
00480 if (gGC) {
00481 XFreeGC(gDisplay, gGC);
00482 gGC = 0;
00483 }
00484 if (gDisplay) {
00485 XSync(gDisplay, False);
00486 XCloseDisplay(gDisplay);
00487 gDisplay = 0;
00488 }
00489 }
00490
00491 void PopdownLogo()
00492 {
00493
00494
00495 gMayPopdown = true;
00496 }
00497
00498 void CloseDisplay()
00499 {
00500
00501
00502 if (gDisplay)
00503 close(ConnectionNumber(gDisplay));
00504 }