xedit.c revision f14f4646
1/* $XConsortium: xedit.c,v 1.28 94/03/26 17:06:28 rws Exp $ */ 2 3/* 4 * COPYRIGHT 1987 5 * DIGITAL EQUIPMENT CORPORATION 6 * MAYNARD, MASSACHUSETTS 7 * ALL RIGHTS RESERVED. 8 * 9 * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND 10 * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. 11 * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR 12 * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 13 * 14 * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, 15 * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT 16 * SET FORTH ABOVE. 17 * 18 * 19 * Permission to use, copy, modify, and distribute this software and its 20 * documentation for any purpose and without fee is hereby granted, provided 21 * that the above copyright notice appear in all copies and that both that 22 * copyright notice and this permission notice appear in supporting 23 * documentation, and that the name of Digital Equipment Corporation not be 24 * used in advertising or publicity pertaining to distribution of the software 25 * without specific, written prior permission. 26 */ 27/* $XFree86: xc/programs/xedit/xedit.c,v 1.17 2002/09/22 07:09:05 paulo Exp $ */ 28 29#include "xedit.h" 30#include <X11/Xaw/SmeBSB.h> 31#include <time.h> 32#include <sys/stat.h> 33#include <X11/CoreP.h> 34 35#include <stdlib.h> 36 37#define randomize() srand((unsigned)time((time_t*)NULL)) 38 39static XtActionsRec actions[] = { 40{"quit", QuitAction}, 41{"save-file", SaveFile}, 42{"load-file", LoadFile}, 43#ifdef INCLUDE_XPRINT_SUPPORT 44{"print-file", PrintFile}, 45#endif /* INCLUDE_XPRINT_SUPPORT */ 46{"find-file", FindFile}, 47{"cancel-find-file", CancelFindFile}, 48{"file-completion", FileCompletion}, 49{"popup-menu", PopupMenu}, 50{"kill-file", KillFile}, 51{"split-window", SplitWindow}, 52{"dir-window", DirWindow}, 53{"delete-window", DeleteWindow}, 54{"xedit-focus", XeditFocus}, 55{"other-window", OtherWindow}, 56{"switch-source", SwitchSource}, 57#ifndef __UNIXOS2__ 58{"lisp-eval", XeditLispEval}, 59{"xedit-print-lisp-eval", XeditPrintLispEval}, 60{"xedit-keyboard-reset",XeditKeyboardReset}, 61#endif 62{"ispell", IspellAction}, 63{"line-edit", LineEditAction}, 64{"tags", TagsAction} 65}; 66 67#define DEF_HINT_INTERVAL 300 /* in seconds, 5 minutes */ 68 69static Atom wm_delete_window; 70static Widget hintswindow; 71static int position_format_mask; 72static XawTextPositionInfo infos[3]; 73 74Widget topwindow, textwindow, messwidget, labelwindow, filenamewindow; 75Widget scratch, hpane, vpanes[2], labels[3], texts[3], forms[3], positions[3]; 76Widget options_popup, dirlabel, dirwindow; 77Boolean international; 78Boolean line_edit; 79XawTextWrapMode wrapmodes[3]; 80 81extern void ResetSourceChanged(xedit_flist_item*); 82 83static void makeButtonsAndBoxes(Widget); 84static void HintsTimer(XtPointer, XtIntervalId*); 85static void PositionChanged(Widget, XtPointer, XtPointer); 86static void StartFormatPosition(void); 87static void StartHints(void); 88 89Display *CurDpy; 90 91struct _app_resources app_resources; 92struct _xedit_flist flist; 93 94#define Offset(field) XtOffsetOf(struct _app_resources, field) 95 96static XtResource resources[] = { 97 {"enableBackups", "EnableBackups", XtRBoolean, sizeof(Boolean), 98 Offset(enableBackups), XtRImmediate, FALSE}, 99 {"backupNamePrefix", "BackupNamePrefix", XtRString, sizeof(char *), 100 Offset(backupNamePrefix),XtRString, ""}, 101 {"backupNameSuffix", "BackupNameSuffix", XtRString, sizeof(char *), 102 Offset(backupNameSuffix),XtRString, ".BAK"}, 103 {"hints", "Hint", XtRString, sizeof(char *), 104 Offset(hints.resource), XtRImmediate, NULL}, 105 {"hintsInterval", XtCInterval, XtRInt, sizeof(long), 106 Offset(hints.interval), XtRImmediate, (XtPointer)DEF_HINT_INTERVAL}, 107 {"changedBitmap", XtRBitmap, XtRString, sizeof(char*), 108 Offset(changed_pixmap_name), XtRString, "dot"}, 109 {"positionFormat", "Format", XtRString, sizeof(char*), 110 Offset(position_format), XtRString, "L%l"}, 111 {"autoReplace", "Replace", XtRString, sizeof(char*), 112 Offset(auto_replace), XtRImmediate, NULL}, 113 {"tagsName", "TagsName", XtRString, sizeof(char *), 114 Offset(tagsName), XtRString, "tags"}, 115 {"loadTags", "LoadTags", XtRBoolean, sizeof(Boolean), 116 Offset(loadTags), XtRImmediate, (XtPointer)TRUE}, 117}; 118 119#undef Offset 120 121#ifdef INCLUDE_XPRINT_SUPPORT 122String fallback_resources[] = { 123 "*international: True", /* set this globally for ALL widgets to avoid wiered crashes */ 124 NULL 125}; 126#endif 127 128int 129main(int argc, char *argv[]) 130{ 131 Boolean exists; 132 char *filename; 133 FileAccess file_access; 134 Widget source; 135 XtAppContext appcon; 136 unsigned int i, num_loaded, lineno; 137 138 num_loaded = lineno = 0; 139 140#ifdef INCLUDE_XPRINT_SUPPORT 141 XtSetLanguageProc(NULL, NULL, NULL); 142#endif 143 topwindow = XtAppInitialize(&appcon, "Xedit", NULL, 0, &argc, argv, 144#ifdef INCLUDE_XPRINT_SUPPORT 145 fallback_resources, 146#else 147 NULL, 148#endif 149 NULL, 0); 150 151 XtAppAddActions(appcon, actions, XtNumber(actions)); 152 XtOverrideTranslations(topwindow, 153 XtParseTranslationTable("<Message>WM_PROTOCOLS: quit()")); 154 155 XtGetApplicationResources(topwindow, (XtPointer) &app_resources, resources, 156 XtNumber(resources), NULL, 0); 157 158 CurDpy = XtDisplay(topwindow); 159 XawSimpleMenuAddGlobalActions(appcon); 160 XtRegisterGrabAction(PopupMenu, True, 161 ButtonPressMask | ButtonReleaseMask, 162 GrabModeAsync, GrabModeAsync); 163 164 makeButtonsAndBoxes(topwindow); 165 166 StartHints(); 167 StartFormatPosition(); 168 (void)StartHooks(appcon); 169 if (position_format_mask == 0) { 170 for (i = 0; i < 3; i++) 171 XtRemoveCallback(texts[i], XtNpositionCallback, 172 PositionChanged, NULL); 173 } 174 XtRealizeWidget(topwindow); 175 176#ifndef __UNIXOS2__ 177 XeditLispInitialize(); 178#endif 179 180 options_popup = XtCreatePopupShell("optionsMenu", simpleMenuWidgetClass, 181 topwindow, NULL, 0); 182 XtRealizeWidget(options_popup); 183 XtAddCallback(XtCreateManagedWidget("ispell", smeBSBObjectClass, 184 options_popup, NULL, 0), 185 XtNcallback, IspellCallback, NULL); 186 CreateEditPopup(); 187 188 wm_delete_window = XInternAtom(XtDisplay(topwindow), "WM_DELETE_WINDOW", 189 False); 190 (void)XSetWMProtocols(XtDisplay(topwindow), XtWindow(topwindow), 191 &wm_delete_window, 1); 192 193 /* This first call is just to save the default font and colors */ 194 UpdateTextProperties(0); 195 196 if (argc > 1) { 197 xedit_flist_item *item; 198 Arg args[2]; 199 unsigned int num_args; 200 201 for (i = 1; i < argc; i++) { 202 struct stat st; 203 204 if (argv[i][0] == '+') { 205 char *endptr; 206 207 lineno = strtol(argv[i], &endptr, 10); 208 /* Don't warn or anything about incorrect input? */ 209 if (*endptr) 210 lineno = 0; 211 continue; 212 } 213 214 filename = ResolveName(argv[i]); 215 if (filename == NULL || FindTextSource(NULL, filename) != NULL) 216 continue; 217 218 num_args = 0; 219 if (stat(filename, &st) == 0 && !S_ISREG(st.st_mode)) { 220 if (S_ISDIR(st.st_mode)) { 221 if (!num_loaded) { 222 char path[BUFSIZ + 1]; 223 224 strncpy(path, filename, sizeof(path) - 2); 225 path[sizeof(path) - 2] = '\0'; 226 if (*path) { 227 if (path[strlen(path) - 1] != '/') 228 strcat(path, "/"); 229 } 230 else 231 strcpy(path, "./"); 232 XtSetArg(args[0], XtNlabel, ""); 233 XtSetValues(dirlabel, args, 1); 234 SwitchDirWindow(True); 235 DirWindowCB(dirwindow, path, NULL); 236 ++num_loaded; 237 } 238 continue; 239 } 240 } 241 242 switch (file_access = CheckFilePermissions(filename, &exists)) { 243 case NO_READ: 244 if (exists) 245 XeditPrintf("File %s exists, and could not be opened for " 246 "reading.\n", argv[i]); 247 else 248 XeditPrintf("File %s does not exist, and the directory " 249 "could not be opened for writing.\n", argv[i]); 250 break; 251 case READ_OK: 252 XtSetArg(args[num_args], XtNeditType, XawtextRead); num_args++; 253 XeditPrintf("File %s opened READ ONLY.\n", argv[i]); 254 break; 255 case WRITE_OK: 256 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 257 XeditPrintf("File %s opened read - write.\n", argv[i]); 258 break; 259 } 260 if (file_access != NO_READ) { 261 int flags; 262 263 if (exists) { 264 flags = EXISTS_BIT; 265 XtSetArg(args[num_args], XtNstring, filename);num_args++; 266 } 267 else { 268 flags = 0; 269 XtSetArg(args[num_args], XtNstring, NULL); num_args++; 270 } 271 source = XtVaCreateWidget("textSource", international ? 272 multiSrcObjectClass 273 : asciiSrcObjectClass, topwindow, 274 XtNtype, XawAsciiFile, 275 XtNeditType, XawtextEdit, 276 NULL, NULL); 277 XtSetValues(source, args, num_args); 278 item = AddTextSource(source, argv[i], filename, 279 flags, file_access); 280 XtAddCallback(item->source, XtNcallback, SourceChanged, 281 (XtPointer)item); 282 if (exists && file_access == WRITE_OK) { 283 item->mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 284 item->mtime = st.st_mtime; 285 } 286 if (!num_loaded) 287 SwitchTextSource(item); 288 ++num_loaded; 289 ResetSourceChanged(item); 290 } 291 } 292 } 293 294 if (!flist.pixmap && strlen(app_resources.changed_pixmap_name)) { 295 XrmValue from, to; 296 297 from.size = strlen(app_resources.changed_pixmap_name); 298 from.addr = app_resources.changed_pixmap_name; 299 to.size = sizeof(Pixmap); 300 to.addr = (XtPointer)&(flist.pixmap); 301 302 XtConvertAndStore(flist.popup, XtRString, &from, XtRBitmap, &to); 303 } 304 305 if (num_loaded == 0) { 306 XtSetKeyboardFocus(topwindow, filenamewindow); 307 XtVaSetValues(textwindow, XtNwrap, XawtextWrapLine, NULL); 308 } 309 else { 310 XtSetKeyboardFocus(topwindow, textwindow); 311 if (lineno) { 312 XawTextPosition position; 313 314 source = XawTextGetSource(textwindow); 315 position = RSCAN(XawTextGetInsertionPoint(textwindow), 316 lineno, False); 317 position = LSCAN(position, 1, False); 318 XawTextSetInsertionPoint(textwindow, position); 319 } 320 } 321 322 XtAppMainLoop(appcon); 323 return EXIT_SUCCESS; 324} 325 326static void 327makeButtonsAndBoxes(Widget parent) 328{ 329 Widget outer, b_row, viewport; 330 Arg arglist[10]; 331 Cardinal num_args; 332 xedit_flist_item *item; 333 static char *labelWindow = "labelWindow", *editWindow = "editWindow"; 334 static char *formWindow = "formWindow", *positionWindow = "positionWindow"; 335 336 outer = XtCreateManagedWidget("paned", panedWidgetClass, parent, 337 NULL, ZERO); 338 339 b_row = XtCreateManagedWidget("buttons", panedWidgetClass, outer, NULL, ZERO); 340 { 341 MakeCommandButton(b_row, "quit", DoQuit); 342 MakeCommandButton(b_row, "save", DoSave); 343 MakeCommandButton(b_row, "load", DoLoad); 344#ifdef INCLUDE_XPRINT_SUPPORT 345 MakeCommandButton(b_row, "print", DoPrint); 346#endif /* INCLUDE_XPRINT_SUPPORT */ 347 filenamewindow = MakeStringBox(b_row, "filename", NULL); 348 } 349 hintswindow = XtCreateManagedWidget("bc_label", labelWidgetClass, 350 outer, NULL, ZERO); 351 352 num_args = 0; 353 XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); ++num_args; 354 messwidget = XtCreateManagedWidget("messageWindow", asciiTextWidgetClass, 355 outer, arglist, num_args); 356 357 num_args = 0; 358 XtSetArg(arglist[num_args], XtNorientation, XtorientHorizontal); ++num_args; 359 hpane = XtCreateManagedWidget("hpane", panedWidgetClass, outer, 360 arglist, num_args); 361 362 num_args = 0; 363 XtSetArg(arglist[num_args], XtNorientation, XtorientVertical); ++num_args; 364 vpanes[0] = XtCreateManagedWidget("vpane", panedWidgetClass, hpane, 365 arglist, num_args); 366 XtSetArg(arglist[num_args], XtNheight, 1); ++num_args; 367 XtSetArg(arglist[num_args], XtNwidth, 1); ++num_args; 368 vpanes[1] = XtCreateWidget("vpane", panedWidgetClass, hpane, 369 arglist, num_args); 370 371 forms[0] = XtCreateManagedWidget(formWindow, formWidgetClass, 372 vpanes[0], NULL, 0); 373 labelwindow = XtCreateManagedWidget(labelWindow,labelWidgetClass, 374 forms[0], NULL, 0); 375 labels[0] = labelwindow; 376 positions[0] = XtCreateManagedWidget(positionWindow,labelWidgetClass, 377 forms[0], NULL, 0); 378 379 forms[2] = XtCreateWidget(formWindow, formWidgetClass, 380 vpanes[1], NULL, 0); 381 labels[2] = XtCreateManagedWidget(labelWindow,labelWidgetClass, 382 forms[2], NULL, 0); 383 positions[2] = XtCreateManagedWidget(positionWindow,labelWidgetClass, 384 forms[2], NULL, 0); 385 386 num_args = 0; 387 XtSetArg(arglist[num_args], XtNtype, XawAsciiFile); ++num_args; 388 XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); ++num_args; 389 textwindow = XtCreateManagedWidget(editWindow, asciiTextWidgetClass, 390 vpanes[0], arglist, num_args); 391 392#ifdef INCLUDE_XPRINT_SUPPORT 393 international = True; 394#else 395 /* Get international resource value form the textwindow */ 396 num_args = 0; 397 XtSetArg(arglist[num_args], XtNinternational, &international); ++num_args; 398 XtGetValues(textwindow, arglist, num_args); 399#endif 400 401 num_args = 0; 402 XtSetArg(arglist[num_args], XtNtype, XawAsciiFile); ++num_args; 403 XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); ++num_args; 404 scratch = XtVaCreateWidget("textSource", international ? 405 multiSrcObjectClass : 406 asciiSrcObjectClass, topwindow, 407 XtNtype, XawAsciiFile, 408 XtNeditType, XawtextEdit, 409 NULL, NULL); 410 XtSetValues(scratch, arglist, num_args); 411 412 num_args = 0; 413 XtSetArg(arglist[num_args], XtNtextSource, scratch); ++num_args; 414 XtSetValues(textwindow, arglist, num_args); 415 416 texts[0] = textwindow; 417 num_args = 0; 418 XtSetArg(arglist[num_args], XtNtextSource, scratch); ++num_args; 419 XtSetArg(arglist[num_args], XtNdisplayCaret, False); ++num_args; 420 texts[2] = XtCreateWidget(editWindow, asciiTextWidgetClass, 421 vpanes[1], arglist, num_args); 422 423 forms[1] = XtCreateWidget(formWindow, formWidgetClass, 424 vpanes[0], NULL, 0); 425 labels[1] = XtCreateManagedWidget(labelWindow,labelWidgetClass, 426 forms[1], NULL, 0); 427 positions[1] = XtCreateManagedWidget(positionWindow,labelWidgetClass, 428 forms[1], NULL, 0); 429 430 texts[1] = XtCreateWidget(editWindow, asciiTextWidgetClass, 431 vpanes[0], arglist, num_args); 432 433 dirlabel = XtCreateWidget("dirlabel", labelWidgetClass, 434 vpanes[1], NULL, 0); 435 num_args = 0; 436 XtSetArg(arglist[num_args], XtNheight, 1); ++num_args; 437 XtSetArg(arglist[num_args], XtNwidth, 1); ++num_args; 438 viewport = XtCreateWidget("viewport", viewportWidgetClass, 439 vpanes[1], arglist, num_args); 440 dirwindow = XtCreateManagedWidget("dirwindow", listWidgetClass, 441 viewport, NULL, 0); 442 443 item = AddTextSource(scratch, "*scratch*", "*scratch*", 444 0, WRITE_OK); 445 item->wrap = XawtextWrapLine; 446 item->flags |= WRAP_BIT; 447 XtAddCallback(item->source, XtNcallback, SourceChanged, 448 (XtPointer)item); 449 ResetSourceChanged(item); 450 flist.current = item; 451 452 for (num_args = 0; num_args < 3; num_args++) 453 XtAddCallback(texts[num_args], XtNpositionCallback, PositionChanged, NULL); 454 455 for (num_args = 0; num_args < 3; num_args++) { 456 XtSetArg(arglist[0], XtNwrap, &wrapmodes[num_args]); 457 XtGetValues(texts[num_args], arglist, 1); 458 } 459 460 XtAddCallback(dirwindow, XtNcallback, DirWindowCB, NULL); 461} 462 463/* Function Name: Feep 464 * Description: feeps the bell. 465 * Arguments: none. 466 * Returns: none. 467 */ 468 469void 470Feep(void) 471{ 472 XBell(CurDpy, 0); 473} 474 475#define l_BIT 0x01 476#define c_BIT 0x02 477#define p_BIT 0x04 478#define s_BIT 0x08 479#define MAX_FMT_LEN 30 480 481static void 482StartFormatPosition(void) 483{ 484 char *fmt = app_resources.position_format; 485 486 if (fmt) 487 while (*fmt) 488 if (*fmt++ == '%') { 489 int len = 0; 490 491 if (*fmt == '-') { 492 ++fmt; 493 ++len; 494 } 495 while (*fmt >= '0' && *fmt <= '9') { 496 ++fmt; 497 if (++len >= MAX_FMT_LEN) { 498 XtAppWarning(XtWidgetToApplicationContext(topwindow), 499 "Format too large to formatPosition"); 500 position_format_mask = 0; 501 return; 502 } 503 } 504 switch (*fmt++) { 505 case 'l': position_format_mask |= l_BIT; break; 506 case 'c': position_format_mask |= c_BIT; break; 507 case 'p': position_format_mask |= p_BIT; break; 508 case 's': position_format_mask |= s_BIT; break; 509 case '%': break; 510 default: { 511 char msg[256]; 512 513 XmuSnprintf(msg, sizeof(msg), 514 "Unknown format \"%%%c\" in positionFormat", 515 fmt[-1]); 516 XtAppWarning(XtWidgetToApplicationContext(topwindow), 517 msg); 518 position_format_mask = 0; 519 return; 520 } 521 } 522 } 523} 524 525/*ARGSUSED*/ 526static void 527PositionChanged(Widget w, XtPointer client_data, XtPointer call_data) 528{ 529 int idx; 530 XawTextPositionInfo *info = (XawTextPositionInfo*)call_data; 531 532 for (idx = 0; idx < 3; idx++) 533 if (w == texts[idx]) 534 break; 535 if (idx > 2) 536 return; 537 538 if (((position_format_mask & l_BIT) 539 && infos[idx].line_number != info->line_number) 540 || ((position_format_mask & c_BIT) 541 && infos[idx].column_number != info->column_number) 542 || ((position_format_mask & p_BIT) 543 && infos[idx].insert_position != info->insert_position) 544 || ((position_format_mask & s_BIT) 545 && infos[idx].last_position != info->last_position) 546 || infos[idx].overwrite_mode != info->overwrite_mode) { 547 int len = 6; 548 Arg args[1]; 549 char buffer[256], *str = app_resources.position_format; 550 char fmt_buf[MAX_FMT_LEN + 2], *fmt; 551 552 memcpy(&infos[idx], info, sizeof(XawTextPositionInfo)); 553 if (info->overwrite_mode) 554 strcpy(buffer, "Ovrwt "); 555 else 556 strcpy(buffer, " "); 557 while (*str) { 558 switch (*str) { 559 case '%': 560 fmt = fmt_buf; 561 *fmt++ = *str++; 562 if (*str == '-') 563 *fmt++ = *str++; 564 /*CONSTCOND*/ 565 while (*str >= '0' && *str <= '9') { 566 /* StartPositionFormat() already checked the format 567 * length. 568 */ 569 *fmt++ = *str++; 570 } 571 *fmt++ = 'd'; 572 *fmt = '\0'; 573 switch (*str) { 574 case 'l': 575 XmuSnprintf(&buffer[len], sizeof(buffer) - len, 576 fmt_buf, info->line_number); 577 break; 578 case 'c': 579 XmuSnprintf(&buffer[len], sizeof(buffer) - len, 580 fmt_buf, info->column_number); 581 break; 582 case 'p': 583 XmuSnprintf(&buffer[len], sizeof(buffer) - len, 584 fmt_buf, info->insert_position); 585 break; 586 case 's': 587 XmuSnprintf(&buffer[len], sizeof(buffer) - len, 588 fmt_buf, info->last_position); 589 break; 590 case '%': 591 strcpy(&buffer[len], "%"); 592 break; 593 } 594 len += strlen(&buffer[len]); 595 break; 596 default: 597 buffer[len++] = *str; 598 break; 599 } 600 if (len >= sizeof(buffer) - 1) 601 break; 602 ++str; 603 } 604 buffer[len] = '\0'; 605 606 XtSetArg(args[0], XtNlabel, buffer); 607 XtSetValues(positions[idx], args, 1); 608 } 609} 610 611/*ARGSUSED*/ 612static void 613HintsTimer(XtPointer closure, XtIntervalId *id) 614{ 615 Arg args[1]; 616 xedit_hints *hints = (xedit_hints*)closure; 617 618 hints->cur_hint = rand() % hints->num_hints; 619 620 XtSetArg(args[0], XtNlabel, hints->hints[hints->cur_hint]); 621 XtSetValues(hintswindow, args, 1); 622 623 hints->timer = XtAppAddTimeOut(XtWidgetToApplicationContext(topwindow), 624 hints->interval, HintsTimer, closure); 625} 626 627#define MAX_HINT_LEN 255 628#define MIN_HINT_INTERVAL 5 629static void 630StartHints(void) 631{ 632 char *str, *p; 633 unsigned i, len; 634 xedit_hints *hints = &(app_resources.hints); 635 636 /* if resource was not set, or was overriden */ 637 if (hints->resource == NULL || !*hints->resource) 638 return; 639 640 randomize(); 641 642 if (hints->interval < MIN_HINT_INTERVAL) 643 hints->interval = DEF_HINT_INTERVAL; 644 hints->interval *= 1000; 645 hints->hints = (char**)XtMalloc(sizeof(char*)); 646 hints->hints[hints->cur_hint = 0] = p = hints->resource; 647 hints->num_hints = 1; 648 649 while ((p = strchr(p, '\n')) != NULL) { 650 if (*++p == '\0') 651 break; 652 hints->hints = (char**) 653 XtRealloc((char*)hints->hints, 654 sizeof(char*) * (hints->num_hints + 1)); 655 hints->hints[hints->num_hints++] = p; 656 } 657 658 /* make a private copy of the resource values, so that one can change 659 * the Xrm database safely. 660 */ 661 for (i = 0; i < hints->num_hints; i++) { 662 if ((p = strchr(hints->hints[i], '\n')) != NULL) 663 len = p - hints->hints[i]; 664 else 665 len = strlen(hints->hints[i]); 666 if (len > MAX_HINT_LEN) 667 len = MAX_HINT_LEN; 668 str = XtMalloc(len + 1); 669 strncpy(str, hints->hints[i], len); 670 str[len] = '\0'; 671 hints->hints[i] = str; 672 } 673 674 hints->timer = XtAppAddTimeOut(XtWidgetToApplicationContext(topwindow), 675 hints->interval, HintsTimer, 676 (XtPointer)hints); 677} 678