home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso / altsrc / articles / 11425 < prev    next >
Text File  |  1994-11-01  |  64KB  |  2,025 lines

  1. Newsgroups: alt.sources
  2. Path: wupost!psuvax1!news.ecn.bgu.edu!willis.cis.uab.edu!ddsw1!panix!news.mathworks.com!europa.eng.gtefsd.com!swiss.ans.net!news.dfn.de!zeus.rbi.informatik.uni-frankfurt.de!terra.wiwi.uni-frankfurt.de!news.th-darmstadt.de!zib-berlin.de!math.fu-berlin.de!fub!bitrot!thomas
  3. From: thomas@bitrot.in-berlin.de (Thomas Driemeyer)
  4. Subject: Re: grok - X/Motif database manager and UI builder, part 05/12
  5. Message-ID: <1994Oct31.213450.10746@bitrot.in-berlin.de>
  6. Organization: /usr/lib/news/organi[sz]ation
  7. References: <1994Oct31.212946.10228@bitrot.in-berlin.de>
  8. Date: Mon, 31 Oct 1994 21:34:50 GMT
  9. Lines: 2014
  10.  
  11. Submitted-by: thomas@bitrot
  12. Archive-name: grok/part05
  13.  
  14. #!/bin/sh
  15. # this is grok.shar.05 (part 5 of grok)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file formwin.c continued
  18. #
  19. if test ! -r _shar_seq_.tmp; then
  20.     echo 'Please unpack part 1 first!'
  21.     exit 1
  22. fi
  23. (read Scheck
  24.  if test "$Scheck" != 5; then
  25.     echo Please unpack part "$Scheck" next!
  26.     exit 1
  27.  else
  28.     exit 0
  29.  fi
  30. ) < _shar_seq_.tmp || exit 1
  31. if test ! -f _shar_wnt_.tmp; then
  32.     echo 'x - still skipping formwin.c'
  33. else
  34. echo 'x - continuing file formwin.c'
  35. sed 's/^X//' << 'SHAR_EOF' >> 'formwin.c' &&
  36. X      case 0x221: (void)read_text_button(w, &item->pattern);    break;
  37. X
  38. X      case 0x222: (void)read_text_button(w, &item->gray_if);    break;
  39. X      case 0x223: (void)read_text_button(w, &item->invisible_if);    break;
  40. X      case 0x224: (void)read_text_button(w, &item->freeze_if);    break;
  41. X      case 0x225: (void)read_text_button(w, &item->skip_if);    break;
  42. X
  43. X      case 0x226: (void)read_text_button(w, &item->pressed);    break;
  44. X      case 0x227: (void)read_text_button(w, &item->added);        break;
  45. X
  46. X      case 0x228: item->ch_vert    ^= TRUE;            break;
  47. X      case 0x229: item->ch_grid    ^= TRUE;            break;
  48. X      case 0x22a: item->ch_axis    ^= TRUE;            break;
  49. X      case 0x22b: item->ch_scroll    ^= TRUE;            break;
  50. X
  51. X      case 0x22c: add_chart_component(item); all = TRUE;        break;
  52. X      case 0x22d: del_chart_component(item); all = TRUE;        break;
  53. X      case 0x230: if (item->ch_curr) item->ch_curr--; all = TRUE;    break;
  54. X      case 0x22f: if (item->ch_curr < item->ch_ncomp-1) item->ch_curr++;
  55. X              all = TRUE;                    break;
  56. X
  57. X      case 0x300: chart->line      = FALSE;            break;
  58. X      case 0x301: chart->line      = TRUE;            break;
  59. X      case 0x302: chart->stacked     ^= TRUE;            break;
  60. X      case 0x303: chart->cuddle     ^= TRUE;            break;
  61. X      case 0x304: chart->exclude_0     ^= TRUE;            break;
  62. X      case 0x305: chart->exclude_neg ^= TRUE;            break;
  63. X      case 0x30a: chart->average = atoi(read_text_button(w, 0));    break;
  64. X      case 0x306: (void)read_text_button(w, &chart->color);        break;
  65. X      case 0x307: (void)read_text_button(w, &chart->value);        break;
  66. X      case 0x308: (void)read_text_button(w, &chart->offset);    break;
  67. X      case 0x309: (void)read_text_button(w, &chart->label);        break;
  68. X
  69. X      case 0x234: (void)read_text_button(w, &item->database);    break;
  70. X      case 0x235: (void)read_text_button(w, &item->query);        break;
  71. X      case 0x231: item->qsummary ^= TRUE;                break;
  72. X      case 0x232: item->qfirst   ^= TRUE;
  73. X               item->qlast     = FALSE;
  74. X              fillout_formedit_widget_by_code(0x233);        break;
  75. X      case 0x233: item->qlast    ^= TRUE;
  76. X               item->qfirst    = FALSE;
  77. X              fillout_formedit_widget_by_code(0x232);        break;
  78. X    }
  79. X
  80. X    /*
  81. X     * if a choice item is modified, modify all other choice items with
  82. X     * the same name too.
  83. X     */
  84. X    if (item && item->name && item->type == IT_CHOICE)
  85. X        for (i=0; i < form->nitems; i++) {
  86. X            ip = form->items[i];
  87. X            if (i != curr_item && ip->type == IT_CHOICE
  88. X                       && ip->name
  89. X                       && !strcmp(ip->name, item->name)) {
  90. X                ip->column   = item->column;
  91. X                ip->search   = item->search;
  92. X                ip->rdonly   = item->rdonly;
  93. X                ip->nosort   = item->nosort;
  94. X                ip->defsort  = item->defsort;
  95. X                  ip->sumcol   = item->sumcol;
  96. X                ip->sumwidth = item->sumwidth;
  97. X                ip->column   = item->column;
  98. X                if (item->idefault) {
  99. X                    if (ip->idefault)
  100. X                        free(ip->idefault);
  101. X                      ip->idefault =mystrdup(item->idefault);
  102. X                }
  103. X            }
  104. X        }
  105. X    return(all ? 2 : 1);
  106. }
  107. SHAR_EOF
  108. echo 'File formwin.c is complete' &&
  109. chmod 0644 formwin.c ||
  110. echo 'restore of formwin.c failed'
  111. Wc_c="`wc -c < 'formwin.c'`"
  112. test 32921 -eq "$Wc_c" ||
  113.     echo 'formwin.c: original size 32921, current size' "$Wc_c"
  114. rm -f _shar_wnt_.tmp
  115. fi
  116. # ============= help.c ==============
  117. if test -f 'help.c' -a X"$1" != X"-c"; then
  118.     echo 'x - skipping help.c (File already exists)'
  119.     rm -f _shar_wnt_.tmp
  120. else
  121. > _shar_wnt_.tmp
  122. echo 'x - extracting help.c (Text)'
  123. sed 's/^X//' << 'SHAR_EOF' > 'help.c' &&
  124. /*
  125. X * print help popup on a particular topic. Help topics are identified by
  126. X * a short string that is looked up in the help file. The help file contains
  127. X * a list of button help entries; each consisting of a line "%% topic"
  128. X * followed by help text lines. Leading blanks in text lines are ignored.
  129. X * Lines beginning with '#' are ignored.
  130. X *
  131. X * To add a help text to a widget, call
  132. X *    XtAddCallback(widget, XmNhelpCallback, help_callback, "topic")
  133. X * and add "%%n topic" and the help text to the help file (n is a number
  134. X * used for extracting a user's manual, it is not used by the grok program).
  135. X *
  136. X * help_callback(parent, topic)        Print help for a topic, usually for
  137. X *                    button <parent>.
  138. X */
  139. X
  140. #include "config.h"
  141. #include <stdio.h>
  142. #include <malloc.h>
  143. #include <Xm/Xm.h>
  144. #include <Xm/DialogS.h>
  145. #include <Xm/Form.h>
  146. #include <Xm/Frame.h>
  147. #include <Xm/LabelP.h>
  148. #include <Xm/LabelG.h>
  149. #include <Xm/PushBP.h>
  150. #include <Xm/PushBG.h>
  151. #include <Xm/ToggleB.h>
  152. #include <Xm/Text.h>
  153. #include <Xm/Protocols.h>
  154. #include <X11/cursorfont.h>
  155. #include "grok.h"
  156. #include "form.h"
  157. X
  158. static void        done_callback(), context_callback();
  159. static char        *get_text();
  160. extern void        *malloc(), *realloc();
  161. extern BOOL        find_file();
  162. X
  163. extern Display        *display;    /* everybody uses the same server */
  164. extern XFontStruct    *font[NFONTS];    /* fonts: FONT_* */
  165. extern XmFontList    fontlist[NFONTS];
  166. extern Pixel        color[NCOLS];    /* colors: COL_* */
  167. extern CARD         *curr_card;    /* card being displayed in main win */
  168. X
  169. static BOOL        have_shell;    /* message popup exists if TRUE */
  170. static Widget        shell;        /* popup menu shell */
  171. X
  172. X
  173. /*
  174. X * destroy the help popup. Remove it from the screen, and destroy its widgets.
  175. X */
  176. X
  177. destroy_help_popup()
  178. {
  179. X    if (have_shell) {
  180. X        XtPopdown(shell);
  181. X        XtDestroyWidget(shell);
  182. X        have_shell = FALSE;
  183. X    }
  184. }
  185. X
  186. X
  187. X
  188. /*
  189. X * look up the help text for <topic> and create a window containing the text.
  190. X */
  191. X
  192. /*ARGSUSED*/
  193. void help_callback(parent, topic)
  194. X    Widget            parent;
  195. X    char            *topic;
  196. {
  197. X    static BOOL        have_fontlist;
  198. X    static XmFontList    fontlist;
  199. X    static Widget        text_w;
  200. X    Widget            form, w;
  201. X    Atom            closewindow;
  202. X    char            *message;
  203. X    Arg            args[20];
  204. X    int            n;
  205. X    int            nlines = 1;
  206. X    char            *p;
  207. X
  208. X    if (!(message = get_text(topic)))
  209. X        return;
  210. X    if (!strcmp(topic, "card") && curr_card && curr_card->form
  211. X                        && curr_card->form->help) {
  212. X        if (!(message = realloc(message, strlen(message) +
  213. X                     strlen(curr_card->form->help) + 2)))
  214. X            return;
  215. X        strcat(message, "\n");
  216. X        strcat(message, curr_card->form->help);
  217. X    }
  218. X    if (have_shell) {
  219. X        XmTextSetString(text_w, message);
  220. X        XtPopup(shell, XtGrabNone);
  221. X        free(message);
  222. X        return;
  223. X    }
  224. X    if (!have_fontlist++)
  225. X        fontlist = XmFontListCreate(font[FONT_HELP], "cset");
  226. X    for (nlines=0, p=message; *p; p++)
  227. X        nlines += *p == '\n';
  228. X    if (nlines > 30)
  229. X        nlines = 30;
  230. X
  231. X    n = 0;
  232. X    XtSetArg(args[n], XmNdeleteResponse,    XmDO_NOTHING);        n++;
  233. X    XtSetArg(args[n], XmNiconic,        False);            n++;
  234. X    shell = XtAppCreateShell("Help", "grok",
  235. X            applicationShellWidgetClass, display, args, n);
  236. X    set_icon(shell, 1);
  237. X    form = XtCreateManagedWidget("helpform", xmFormWidgetClass,
  238. X            shell, NULL, 0);
  239. X    XtAddCallback(form, XmNhelpCallback, (XtCallbackProc)help_callback,
  240. X                            (XtPointer)"help");
  241. X
  242. X                            /*-- buttons --*/
  243. X    n = 0;
  244. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  245. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  246. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  247. X    XtSetArg(args[n], XmNrightOffset,    8);            n++;
  248. X    XtSetArg(args[n], XmNwidth,        80);            n++;
  249. X    w = XtCreateManagedWidget("Dismiss", xmPushButtonWidgetClass,
  250. X            form, args, n);
  251. X    XtAddCallback(w, XmNactivateCallback, done_callback, (XtPointer)0);
  252. X    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)help_callback,
  253. X                        (XtPointer)"help_done");
  254. X    n = 0;
  255. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  256. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  257. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  258. X    XtSetArg(args[n], XmNrightWidget,    w);            n++;
  259. X    XtSetArg(args[n], XmNrightOffset,    8);            n++;
  260. X    XtSetArg(args[n], XmNwidth,        80);            n++;
  261. X    w = XtCreateManagedWidget("Context", xmPushButtonWidgetClass,
  262. X            form, args, n);
  263. X    XtAddCallback(w, XmNactivateCallback, context_callback, (XtPointer)0);
  264. X    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)help_callback,
  265. X                            (XtPointer)"help_ctx");
  266. X
  267. X                            /*-- text --*/
  268. X    n = 0;
  269. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  270. X    XtSetArg(args[n], XmNtopOffset,        8);            n++;
  271. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_WIDGET);    n++;
  272. X    XtSetArg(args[n], XmNbottomWidget,    w);            n++;
  273. X    XtSetArg(args[n], XmNbottomOffset,    16);            n++;
  274. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  275. X    XtSetArg(args[n], XmNleftOffset,    8);            n++;
  276. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  277. X    XtSetArg(args[n], XmNrightOffset,    8);            n++;
  278. X    XtSetArg(args[n], XmNhighlightThickness,0);            n++;
  279. X    XtSetArg(args[n], XmNeditable,        False);            n++;
  280. X    XtSetArg(args[n], XmNeditMode,        XmMULTI_LINE_EDIT);    n++;
  281. X    XtSetArg(args[n], XmNcolumns,        60);            n++;
  282. X    XtSetArg(args[n], XmNrows,        nlines+1);        n++;
  283. X    XtSetArg(args[n], XmNfontList,        fontlist);        n++;
  284. X    XtSetArg(args[n], XmNscrollVertical,    True);            n++;
  285. X    XtSetArg(args[n], XmNpendingDelete,    False);            n++;
  286. X    text_w = w = XmCreateScrolledText(form, "text", args, n);
  287. X    XmTextSetString(w, message);
  288. X    XtVaSetValues(w, XmNbackground,    color[COL_SHEET], NULL);
  289. X    XtManageChild(w);
  290. X    XtAddCallback(w, XmNhelpCallback, (XtCallbackProc)help_callback,
  291. X                            (XtPointer)"help");
  292. X    XtPopup(shell, XtGrabNone);
  293. X    closewindow = XmInternAtom(display, "WM_DELETE_WINDOW", False);
  294. X    XmAddWMProtocolCallback(shell, closewindow,
  295. X                    done_callback, (XtPointer)shell);
  296. X    have_shell = TRUE;
  297. X    free(message);
  298. }
  299. X
  300. X
  301. /*ARGSUSED*/
  302. static void done_callback(widget, item, data)
  303. X    Widget                widget;
  304. X    int                item;
  305. X    XmToggleButtonCallbackStruct    *data;
  306. {
  307. X    destroy_help_popup();
  308. }
  309. X
  310. X
  311. /*ARGSUSED*/
  312. static void context_callback(widget, item, data)
  313. X    Widget                widget;
  314. X    int                item;
  315. X    XmToggleButtonCallbackStruct    *data;
  316. {
  317. X    Widget w;
  318. X    Cursor cursor = XCreateFontCursor(display, XC_question_arrow);
  319. X    if (w = XmTrackingLocate(shell, cursor, False)) {
  320. X        data->reason = XmCR_HELP;
  321. X        XtCallCallbacks(w, XmNhelpCallback, &data);
  322. X    }
  323. X    XFreeCursor(display, cursor);
  324. }
  325. X
  326. X
  327. /*ARGSUSED*/
  328. static char *get_text(topic)
  329. X    char            *topic;
  330. {
  331. X    FILE            *fp;        /* help file */
  332. X    char            line[1024];    /* line buffer (and filename)*/
  333. X    char            *text;        /* text buffer */
  334. X    int            textsize;    /* size of text buffer */
  335. X    int            textlen = 0;    /* # of chars in text buffer */
  336. X    int            n;        /* for stripping trailing \n */
  337. X    register char        *p;
  338. X
  339. X    if (!(text = (char *)malloc(textsize = 4096)))
  340. X        return(0);
  341. X    *text = 0;
  342. X    if (!find_file(line, HELP_FN, FALSE) || !(fp = fopen(line, "r"))) {
  343. X        sprintf(text, "Sorry, no help available,\n%s not found",
  344. X                                HELP_FN);
  345. X        return(text);
  346. X    }
  347. X    for (;;) {                    /* find topic */
  348. X        if (!fgets(line, 1024, fp)) {
  349. X            strcpy(text, "Sorry, no help available on this topic");
  350. X            return(text);
  351. X        }
  352. X        if (line[0] != '%' || line[1] != '%')
  353. X            continue;
  354. X        line[strlen(line)-1] = 0; /* strip \n */
  355. X        for (p=line+2; *p >= '0' && *p <= '9'; p++);
  356. X        for (; *p == ' ' || *p == '\t'; p++);
  357. X        if (*p && *p != '\n' && !strcmp(p, topic))
  358. X            break;
  359. X    }
  360. X    for (;;) {                    /* read text */
  361. X        if (!fgets(line, 1024, fp))
  362. X            break;
  363. X        if (line[0] == '#')
  364. X            continue;
  365. X        if (line[0] == '%' && line[1] == '%')
  366. X            return(text);
  367. X        p = line[0] == '\t' ? line+1 : line;
  368. X        if (textlen + strlen(p) > textsize)
  369. X            if (!(text = (char *)realloc(text, textsize += 4096)))
  370. X                break;
  371. X        strcat(text, p);
  372. X        textlen += strlen(p);
  373. X    }
  374. X    for (n=strlen(text); n && text[n-1] == '\n'; n--)
  375. X        text[n-1] = 0;
  376. X    return(text);
  377. }
  378. SHAR_EOF
  379. chmod 0644 help.c ||
  380. echo 'restore of help.c failed'
  381. Wc_c="`wc -c < 'help.c'`"
  382. test 7585 -eq "$Wc_c" ||
  383.     echo 'help.c: original size 7585, current size' "$Wc_c"
  384. rm -f _shar_wnt_.tmp
  385. fi
  386. # ============= main.c ==============
  387. if test -f 'main.c' -a X"$1" != X"-c"; then
  388.     echo 'x - skipping main.c (File already exists)'
  389.     rm -f _shar_wnt_.tmp
  390. else
  391. > _shar_wnt_.tmp
  392. echo 'x - extracting main.c (Text)'
  393. sed 's/^X//' << 'SHAR_EOF' > 'main.c' &&
  394. /*
  395. X * Initializes everything and starts a calendar window for the current
  396. X * month. The interval timer (for autosave and entry recycling) and a
  397. X * few routines used by everyone are also here.
  398. X *
  399. X *    main(argc, argv)        Guess.
  400. X *
  401. X * Author: thomas@bitrot.in-berlin.de (Thomas Driemeyer)
  402. X */
  403. X
  404. #include "config.h"
  405. #include <stdio.h>
  406. #include <unistd.h>
  407. #include <errno.h>
  408. #include <string.h>
  409. #include <time.h>
  410. #include <sys/types.h>
  411. #include <Xm/Xm.h>
  412. #include <X11/StringDefs.h>
  413. #include "grok.h"
  414. #include "form.h"
  415. #include "version.h"
  416. X
  417. extern char *mystrdup();
  418. static void init_resources(), init_colors(), init_fonts();
  419. static void usage();
  420. X
  421. extern char        *resolve_tilde();
  422. extern void        switch_form();
  423. static void        make_grokdir();
  424. X
  425. extern CARD         *curr_card;    /* card switched to if -t */
  426. extern Widget        w_summary;    /* form for summary table */
  427. extern Widget        mainwindow;    /* popup menus hang off main window */
  428. Display            *display;    /* everybody uses the same server */
  429. GC            gc;        /* everybody uses this context */
  430. GC            xor_gc;        /* XOR gc for rubberbanding */
  431. XXtAppContext        app;        /* application handle */
  432. Widget            toplevel;    /* top-level shell for icon name */
  433. char            *progname;    /* argv[0] */
  434. XXFontStruct        *font[NFONTS];    /* fonts: FONT_* */
  435. XXmFontList        fontlist[NFONTS];
  436. Pixel            color[NCOLS];    /* colors: COL_* */
  437. Pixmap            pixmap[NPICS];    /* common symbols */
  438. X
  439. X
  440. static String fallbacks[] = {
  441. #include "resource.h"
  442. X    NULL
  443. };
  444. X
  445. X
  446. /*
  447. X * initialize everything and create the main calendar window
  448. X */
  449. X
  450. main(argc, argv)
  451. X    int        argc;
  452. X    char        *argv[];
  453. {
  454. X    int        n, i;
  455. X    char        *formname = 0;
  456. X    char        *query = 0;
  457. X    BOOL        nofork = FALSE;
  458. X    BOOL        ttymode = FALSE;
  459. X    BOOL        noheader = FALSE;
  460. X    char        *errmsg;
  461. X    XGCValues    gcval;
  462. X
  463. X    if ((progname = strrchr(argv[0], '/')) && progname[1])
  464. X        progname++;
  465. X    else
  466. X        progname = argv[0];
  467. X
  468. X    for (n=1; n < argc; n++)            /* options */
  469. X        if (*argv[n] != '-')
  470. X            if (!formname)
  471. X                formname = argv[n];
  472. X            else if (!query)
  473. X                query = argv[n];
  474. X            else
  475. X                usage();
  476. X
  477. X        else if (argv[n][2] < 'a' || argv[n][2] > 'z')
  478. X            switch(argv[n][1]) {
  479. X              case 'd':
  480. X                for (i=0; fallbacks[i]; i++)
  481. X                    printf("%s%s\n", progname,
  482. X                             fallbacks[i]);
  483. X                fflush(stdout);
  484. X                return(0);
  485. X              case 'v':
  486. X                fprintf(stderr, "%s: %s\n", progname, VERSION);
  487. X                return(0);
  488. X              case 'f':
  489. X                nofork = TRUE;
  490. X                break;
  491. X              case 'T':
  492. X                noheader = TRUE;
  493. X              case 't':
  494. X                ttymode = TRUE;
  495. X                break;
  496. X              default:
  497. X                usage();
  498. X            }
  499. X
  500. X    (void)umask(0077);
  501. X    tzset();
  502. X    if (ttymode) {
  503. X        char buf[1024];
  504. X        if (!formname)
  505. X            usage();
  506. X        init_resources();
  507. X        read_preferences();
  508. X        switch_form(formname);
  509. X        if (!curr_card ||!curr_card->dbase ||!curr_card->dbase->nrows){
  510. X            fprintf(stderr, "%s: %s: no data\n",progname,formname);
  511. X            _exit(0);
  512. X        }
  513. X        query_any(curr_card, query);
  514. X        if (!curr_card->nquery) {
  515. X            fprintf(stderr,"%s: %s: no match\n",progname,formname);
  516. X            _exit(0);
  517. X        }
  518. X        if (!noheader) {
  519. X            char *p;
  520. X            make_summary_line(buf, curr_card, -1);
  521. X            puts(buf);
  522. X            for (p=buf; *p; p++)
  523. X                *p = '-';
  524. X            puts(buf);
  525. X        }
  526. X        for (n=0; n < curr_card->nquery; n++) {
  527. X            make_summary_line(buf, curr_card, curr_card->query[n]);
  528. X            puts(buf);
  529. X        }
  530. X        _exit(0);
  531. X    }
  532. X    if (!nofork) {                    /* background */
  533. X        long pid = fork();
  534. X        if (pid < 0)
  535. X            perror("can't fork");
  536. X        else if (pid > 0)
  537. X            _exit(0);
  538. X    }
  539. X    toplevel = XtAppInitialize(&app, "Grok", NULL, 0,
  540. #        ifndef XlibSpecificationRelease
  541. X                (Cardinal *)&argc, argv,
  542. #        else
  543. X                &argc, argv,
  544. #        endif
  545. X                fallbacks, NULL, 0);
  546. X    display = XtDisplay(toplevel);
  547. X    set_icon(toplevel, 0);
  548. X    gc     = XCreateGC(display, DefaultRootWindow(display), 0, 0);
  549. X    xor_gc = XCreateGC(display, DefaultRootWindow(display), 0, 0);
  550. X    gcval.function = GXxor;
  551. X    (void)XChangeGC(display, xor_gc, GCFunction, &gcval);
  552. X    XSetForeground(display, xor_gc,
  553. X            WhitePixelOfScreen(DefaultScreenOfDisplay(display)));
  554. X
  555. X    init_resources();
  556. X    init_colors();
  557. X    init_fonts();
  558. X    init_pixmaps();
  559. X    read_preferences();
  560. X    XSetForeground(display, xor_gc, color[COL_CANVBACK]);
  561. X
  562. X    create_mainwindow(toplevel);
  563. X    XtRealizeWidget(toplevel);
  564. X
  565. X    make_grokdir();
  566. X
  567. X    if (formname)
  568. X        switch_form(formname);
  569. X    if (query) {
  570. X        query_any(curr_card, query);
  571. X        create_summary_menu(curr_card, w_summary, mainwindow);
  572. X        curr_card->row = curr_card->query ? curr_card->query[0]
  573. X                          : curr_card->dbase->nrows;
  574. X        fillout_card(curr_card, FALSE);
  575. X    }
  576. X    XtAppMainLoop(app);
  577. X    return(0);
  578. }
  579. X
  580. X
  581. /*
  582. X * usage information
  583. X */
  584. X
  585. static void usage()
  586. {
  587. X    fprintf(stderr, "Usage: %s [options] [form ['query']]\n", progname);
  588. X    fprintf(stderr, "    Options:\n%s%s%s%s%s%s\n",
  589. X            "\t-h\tprint this help text\n",
  590. X            "\t-d\tdump fallback app-defaults and exit\n",
  591. X            "\t-v\tprint version string\n",
  592. X            "\t-t\tprint cards matching query to stdout\n",
  593. X            "\t-T\tsame as -t without header line\n",
  594. X            "\t-f\tdon't fork on startup\n");
  595. X    fprintf(stderr, "    the form argument is required for -t and -T.\n");
  596. X    _exit(1);
  597. }
  598. X
  599. X
  600. /*
  601. X * create the directory that holds all forms and databases. This is a
  602. X * separate routine to avoid having a big buffer on the stack in main().
  603. X */
  604. X
  605. static void mkdir_callback()
  606. {
  607. X    char *path = resolve_tilde(GROKDIR, 0);
  608. X    (void)chmod(path, 0700);
  609. X    (void)mkdir(path, 0700);
  610. X    if (access(path, X_OK))
  611. X        create_error_popup(toplevel, errno,
  612. X                    "Cannot create directory %s", path);
  613. }
  614. X
  615. static void make_grokdir()
  616. {
  617. X    char *path = resolve_tilde(GROKDIR, 0);
  618. X    if (access(path, X_OK))
  619. X        create_query_popup(toplevel, mkdir_callback, 0,
  620. "Cannot access directory %s\n\n\
  621. This directory is required to store the grok configuration\n\
  622. file, and it is the default location for forms and databases.\n\
  623. If you are running grok for the first time and intend to use it\n\
  624. regularly, press OK now and copy all files from the grokdir\n\
  625. demo directory in the grok distribution into %s .\n\
  626. \n\
  627. If you want to experiment with grok first, press Cancel. If\n\
  628. you have a grokdir directory in the directory you started\n\
  629. grok from, it will be used in place of %s, but you may\n\
  630. not be able to create new forms and databases, and con-\n\
  631. figuration changes will not be saved.",
  632. X                        path, GROKDIR, GROKDIR);
  633. }
  634. X
  635. X
  636. /*------------------------------------ init ---------------------------------*/
  637. /*
  638. X * read resources and put them into the config struct. This routine is used
  639. X * for getting three types of resources: res_type={XtRInt,XtRBool,XtRString}.
  640. X */
  641. X
  642. void get_rsrc(ret, res_name, res_class_name, res_type)
  643. X    XtPointer    ret;
  644. X    char        *res_name;
  645. X    char        *res_class_name;
  646. X    char        *res_type;
  647. {
  648. X    XtResource    res_list[1];
  649. X
  650. X    res_list->resource_name      = res_name;
  651. X    res_list->resource_class  = res_class_name;
  652. X    res_list->resource_type      = res_type;
  653. X    res_list->resource_size      = sizeof(res_type);
  654. X    res_list->resource_offset = 0;
  655. X    res_list->default_type      = res_type;
  656. X    res_list->default_addr      = 0;
  657. X
  658. X    XtGetApplicationResources(toplevel, ret, res_list, 1, NULL, 0);
  659. }
  660. X
  661. X
  662. static void init_resources()
  663. {
  664. #if 0
  665. X    register struct config    *c = &config;
  666. X
  667. X    get_rsrc(&c->calbox_xs,        "calBoxWidth",  "CalBoxWidth",  XtRInt);
  668. #endif
  669. }
  670. X
  671. X
  672. /*
  673. X * determine all colors, and allocate them. They can then be used by a call
  674. X * to set_color(COL_XXX).
  675. X */
  676. X
  677. static void init_colors()
  678. {
  679. X    Screen            *screen = DefaultScreenOfDisplay(display);
  680. X    Colormap        cmap;
  681. X    XColor            rgb;
  682. X    int            i, d;
  683. X    char            *c, *n, class_name[256];
  684. X
  685. X    cmap = DefaultColormap(display, DefaultScreen(display));
  686. X    for (i=0; i < NCOLS; i++) {
  687. X        switch (i) {
  688. X          default:
  689. X          case COL_STD:        n = "colStd";        d=1;    break;
  690. X          case COL_BACK:    n = "colBack";        d=0;    break;
  691. X          case COL_SHEET:    n = "colSheet";        d=0;    break;
  692. X          case COL_TEXTBACK:    n = "colTextBack";    d=0;    break;
  693. X          case COL_TOGGLE:    n = "colToggle";    d=1;    break;
  694. X          case COL_CANVBACK:    n = "colCanvBack";    d=0;    break;
  695. X          case COL_CANVFRAME:    n = "colCanvFrame";    d=1;    break;
  696. X          case COL_CANVBOX:    n = "colCanvBox";    d=0;    break;
  697. X          case COL_CANVSEL:    n = "colCanvSel";    d=1;    break;
  698. X          case COL_CANVTEXT:    n = "colCanvText";    d=1;    break;
  699. X          case COL_CHART_AXIS:    n = "colChartAxis";    d=1;    break;
  700. X          case COL_CHART_GRID:    n = "colChartGrid";    d=1;    break;
  701. X          case COL_CHART_BOX:    n = "colChartBox";    d=1;    break;
  702. X          case COL_CHART_0:    n = "colChart0";    d=0;    break;
  703. X          case COL_CHART_1:    n = "colChart1";    d=0;    break;
  704. X          case COL_CHART_2:    n = "colChart2";    d=0;    break;
  705. X          case COL_CHART_3:    n = "colChart3";    d=0;    break;
  706. X          case COL_CHART_4:    n = "colChart4";    d=0;    break;
  707. X          case COL_CHART_5:    n = "colChart5";    d=0;    break;
  708. X          case COL_CHART_6:    n = "colChart6";    d=0;    break;
  709. X          case COL_CHART_7:    n = "colChart7";    d=0;    break;
  710. X        }
  711. X        strcpy(class_name, n);
  712. X        class_name[0] &= ~('a'^'A');
  713. X        get_rsrc(&c, n, class_name, XtRString);
  714. X        if (!XParseColor(display, cmap, c, &rgb))
  715. X            fprintf(stderr, "%s: unknown color \"%s\" (%s)\n",
  716. X                            progname, c, n);
  717. X        else if (!XAllocColor(display, cmap, &rgb))
  718. X            fprintf(stderr, "%s: can't alloc color \"%s\" (%s)\n",
  719. X                            progname, c, n);
  720. X        else {
  721. X            color[i] = rgb.pixel;
  722. X            continue;
  723. X        }
  724. X        color[i] = d ? BlackPixelOfScreen(screen)
  725. X                 : WhitePixelOfScreen(screen);
  726. X    }
  727. }
  728. X
  729. X
  730. set_color(col)
  731. X    int            col;
  732. {
  733. X    XSetForeground(display, gc, color[col]);
  734. }
  735. X
  736. X
  737. /*
  738. X * load all fonts and make them available in the "fonts" struct. They are
  739. X * loaded into the GC as necessary.
  740. X */
  741. X
  742. static void init_fonts()
  743. {
  744. X    int            i;
  745. X    char            *f, class_name[256];
  746. X
  747. X    for (i=0; i < NFONTS; i++) {
  748. X        switch (i) {
  749. X          default:
  750. X          case FONT_STD:    f = "fontList";            break;
  751. X          case FONT_HELP:    f = "helpFont";            break;
  752. X          case FONT_HELV:    f = "helvFont";            break;
  753. X          case FONT_HELV_O:    f = "helvObliqueFont";        break;
  754. X          case FONT_HELV_S:    f = "helvSmallFont";        break;
  755. X          case FONT_HELV_L:    f = "helvLargeFont";        break;
  756. X          case FONT_COURIER:    f = "courierFont";        break;
  757. X          case FONT_LABEL:    f = "labelFont";        break;
  758. X        }
  759. X        strcpy(class_name, f);
  760. X        class_name[0] &= ~('a'^'A');
  761. X        get_rsrc(&f, f, class_name, XtRString);
  762. X        if (!(font[i] = XLoadQueryFont(display, f)))
  763. X            fatal("can't load font \"%s\"\n", f);
  764. X        if (!(fontlist[i] = XmFontListCreate(font[i], "cset")))
  765. X            fatal("can't create fontlist \"%s\"\n", f);
  766. X    }
  767. }
  768. X
  769. X
  770. /*
  771. X * allocate pixmaps
  772. X */
  773. X
  774. #include "bm_left.h"
  775. #include "bm_right.h"
  776. X
  777. static char *pics[NPICS]     = { bm_left_bits,   bm_right_bits };
  778. static int pix_width[NPICS]  = { bm_left_width,  bm_right_width };
  779. static int pix_height[NPICS] = { bm_left_height, bm_right_height };
  780. X
  781. init_pixmaps()
  782. {
  783. X    int            p;
  784. X    Colormap        cmap;
  785. X    XColor            rgb;
  786. X    char            *c;
  787. X
  788. X    cmap = DefaultColormap(display, DefaultScreen(display));
  789. X    get_rsrc(&c, "background", "Background", XtRString);
  790. X    if (!XParseColor(display, cmap, c, &rgb))
  791. X        fprintf(stderr, "pixmap error: unknown bkg color \"%s\"\n", c);
  792. X    if (!XAllocColor(display, cmap, &rgb))
  793. X        fprintf(stderr, "pixmap error: can't alloc bkg color \"%s\"\n",
  794. X                                    c);
  795. X    for (p=0; p < NPICS; p++)
  796. X        if (!(pixmap[p] = XCreatePixmapFromBitmapData(display,
  797. X                DefaultRootWindow(display),
  798. X                pics[p], pix_width[p], pix_height[p],
  799. X                color[COL_STD], rgb.pixel,
  800. X                DefaultDepth(display,DefaultScreen(display)))))
  801. X            fatal("no memory for pixmaps");
  802. }
  803. SHAR_EOF
  804. chmod 0644 main.c ||
  805. echo 'restore of main.c failed'
  806. Wc_c="`wc -c < 'main.c'`"
  807. test 10853 -eq "$Wc_c" ||
  808.     echo 'main.c: original size 10853, current size' "$Wc_c"
  809. rm -f _shar_wnt_.tmp
  810. fi
  811. # ============= mainwin.c ==============
  812. if test -f 'mainwin.c' -a X"$1" != X"-c"; then
  813.     echo 'x - skipping mainwin.c (File already exists)'
  814.     rm -f _shar_wnt_.tmp
  815. else
  816. > _shar_wnt_.tmp
  817. echo 'x - extracting mainwin.c (Text)'
  818. sed 's/^X//' << 'SHAR_EOF' > 'mainwin.c' &&
  819. /*
  820. X * Create the main window and everything in it.
  821. X *
  822. X *    create_mainwindow(toplvl)    Create all widgets in main window
  823. X *    print_info_line()        print database status into main window
  824. X *    remake_dbase_pulldown()        put known forms into dbase pulldown
  825. X *    remake_query_pulldown()        put predefined queries into pulldown
  826. X *    remake_sort_pulldown()        put sort criteria into sort pulldown
  827. X *    switch_form(formname)        switch mainwindow to new form
  828. X *    search_cards(card,string)    do a query for an expression or string
  829. X */
  830. X
  831. #include "config.h"
  832. #ifndef NOSTDLIB
  833. #include <stdlib.h>
  834. #endif
  835. #include <stdio.h>
  836. #include <time.h>
  837. #include <sys/types.h>
  838. #ifdef DIRECT
  839. #include <sys/dir.h>
  840. #define  dirent direct
  841. #else
  842. #include <dirent.h>
  843. #endif
  844. #include <Xm/Xm.h>
  845. #include <Xm/MainW.h>
  846. #include <Xm/Separator.h>
  847. #include <Xm/Form.h>
  848. #include <Xm/Frame.h>
  849. #include <Xm/LabelP.h>
  850. #include <Xm/ArrowBP.h>
  851. #include <Xm/ArrowBG.h>
  852. #include <Xm/Text.h>
  853. #include <Xm/PushBP.h>
  854. #include <Xm/PushBG.h>
  855. #include <X11/cursorfont.h>
  856. #include "grok.h"
  857. #include "form.h"
  858. X
  859. #define OFF        16        /* margin around summary and card */
  860. #define NHIST        20        /* remember this many search strings */
  861. X
  862. #ifndef LIB
  863. #define LIB "/usr/local/lib"
  864. #endif
  865. X
  866. extern FORM  *form_create();
  867. extern DBASE *dbase_create();
  868. extern CARD  *create_card_menu();
  869. extern char *resolve_tilde(), *mystrdup(), *evaluate();
  870. extern void help_callback();
  871. static void file_pulldown(), dbase_pulldown(), help_pulldown();
  872. static void search_callback(), new_callback(), del_callback();
  873. static void pos_callback(), query_pulldown(), sort_pulldown();
  874. static void newform_pulldown(), letter_callback();
  875. X
  876. extern Display        *display;    /* everybody uses the same server */
  877. extern GC        gc;        /* everybody uses this context */
  878. extern struct config    config;        /* global configuration data */
  879. extern Pixel        color[NCOLS];    /* colors: COL_* */
  880. extern Pixmap        pixmap[NPICS];    /* common symbols */
  881. extern XmFontList    fontlist[NFONTS];
  882. extern struct pref    pref;        /* global preferences */
  883. extern int        col_sorted_by;    /* dbase is sorted by this column */
  884. CARD             *curr_card;    /* card being displayed in main win, */
  885. char            *prev_form;    /* previous form name */
  886. Widget            mainwindow;    /* popup menus hang off main window */
  887. static Dimension    win_xs, win_ys;    /* size of main window w/o sum+card */
  888. static Widget        toplevel;    /* need to save this for icon name */
  889. static Widget        menubar;    /* menu bar in main window */
  890. static Widget        dbpulldown;    /* dbase pulldown menu widget */
  891. static Widget        sortpulldown;    /* sort  pulldown menu widget */
  892. static Widget        qpulldown;    /* query pulldown menu widget */
  893. X
  894. static Widget        w_info;        /* info label, for "n found" */
  895. static Widget        w_search;    /* search string text widget */
  896. static Widget        w_prev;        /* search prev arrow */
  897. static Widget        w_next;        /* search next arrow */
  898. X       Widget        w_summary;    /* form for summary table */
  899. static Widget        w_letter[28];    /* buttons for a,b,c,...,z,misc,* */
  900. static Widget        w_card;        /* form for card */
  901. static Widget        w_left;        /* button: previous card */
  902. static Widget        w_right;    /* button: next card */
  903. static Widget        w_new;        /* button: start a new card */
  904. static Widget        w_del;        /* button: delete current card */
  905. X
  906. X
  907. X
  908. /*
  909. X * create the main window with a menu bar and empty forms for the summary
  910. X * and the card. The forms will be filled later. This routine is called
  911. X * once during startup, before the first switch_form().
  912. X */
  913. X
  914. create_mainwindow(toplvl)
  915. X    Widget        toplvl;
  916. {
  917. X    XmString    s[10];
  918. X    Widget        menu, fmenu, form, w, searchform;
  919. X    Arg        args[15];
  920. X    int        n, i, wid;
  921. X    char        buf[10];
  922. X
  923. X    toplevel = toplvl;
  924. X    mainwindow = XtCreateManagedWidget("mainwindow",
  925. X            xmMainWindowWidgetClass, toplevel, NULL, 0);
  926. X
  927. X                            /*-- menu bar --*/
  928. X    s[0] = XmStringCreateSimple("File");
  929. X    s[1] = XmStringCreateSimple("Database");
  930. X    s[2] = XmStringCreateSimple("Sort");
  931. X    s[3] = XmStringCreateSimple("Query");
  932. X    s[4] = XmStringCreateSimple("Help");
  933. X    menubar = XmVaCreateSimpleMenuBar(mainwindow, "menubar",
  934. X            FIX_MENUBAR
  935. X            XmVaCASCADEBUTTON, s[0], 'F',
  936. X            XmVaCASCADEBUTTON, s[1], 'D',
  937. X            XmVaCASCADEBUTTON, s[2], 'S',
  938. X            XmVaCASCADEBUTTON, s[3], 'Q',
  939. X            XmVaCASCADEBUTTON, s[4], 'H',
  940. X            NULL);
  941. X    if (w = XtNameToWidget(menubar, "button_4"))
  942. X        XtVaSetValues(menubar, XmNmenuHelpWidget, w, 0);
  943. X    for (n=0; n < 5; n++)
  944. X        XmStringFree(s[n]);
  945. X
  946. X    s[0] = XmStringCreateSimple("Print...");
  947. X    s[1] = XmStringCreateSimple("Preferences...");
  948. X    s[2] = XmStringCreateSimple("Form editor");
  949. X    s[3] = XmStringCreateSimple("About...");
  950. X    s[4] = XmStringCreateSimple("Save");
  951. X    s[5] = XmStringCreateSimple("Quit");
  952. X    s[6] = XmStringCreateSimple("Rambo Quit");
  953. X    s[7] = XmStringCreateSimple("Ctrl-P");
  954. X    s[8] = XmStringCreateSimple("Ctrl-R");
  955. X    s[9] = XmStringCreateSimple("Ctrl-S");
  956. X    fmenu = XmVaCreateSimplePulldownMenu(menubar, "file", 0,
  957. X            file_pulldown,
  958. X            FIX_MENUBAR
  959. X            XmVaPUSHBUTTON,    s[0], 'P',  "Ctrl<Key>P", s[7],
  960. X            XmVaPUSHBUTTON,    s[1], 'r',  "Ctrl<Key>R", s[8],
  961. X            XmVaCASCADEBUTTON, s[2], 'F',
  962. X            XmVaPUSHBUTTON,    s[3], 'A',  NULL, NULL,
  963. X            XmVaPUSHBUTTON,    s[4], 'S',  "Ctrl<Key>S", s[9],
  964. X            XmVaPUSHBUTTON,    s[5], 'Q',  NULL, NULL,
  965. X            XmVaPUSHBUTTON,    s[6], NULL, NULL, NULL,
  966. X            NULL);
  967. #ifdef XmNtearOffModel
  968. X    XtVaSetValues(fmenu, XmNtearOffModel, XmTEAR_OFF_ENABLED, NULL);
  969. #endif
  970. X    XtAddCallback(fmenu, XmNhelpCallback,
  971. X                    help_callback, (XtPointer)"pd_file");
  972. X    for (n=0; n < 10; n++)
  973. X        XmStringFree(s[n]);
  974. X
  975. X    s[0] = XmStringCreateSimple("Edit current form...");
  976. X    s[1] = XmStringCreateSimple("Create new form from scratch...");
  977. X    s[2] = XmStringCreateSimple("Create, use current as template...");
  978. X    fmenu = XmVaCreateSimplePulldownMenu(fmenu, "newform", 2,
  979. X            newform_pulldown,
  980. X            FIX_MENUBAR
  981. X            XmVaPUSHBUTTON,    s[0], 'E',  NULL, NULL,
  982. X            XmVaPUSHBUTTON,    s[1], 'C',  NULL, NULL,
  983. X            XmVaPUSHBUTTON,    s[2], 't',  NULL, NULL,
  984. X            NULL);
  985. #ifdef XmNtearOffModel
  986. X    XtVaSetValues(fmenu, XmNtearOffModel, XmTEAR_OFF_ENABLED, NULL);
  987. #endif
  988. X    XtAddCallback(fmenu, XmNhelpCallback,
  989. X                    help_callback, (XtPointer)"pd_file");
  990. X    for (n=0; n < 3; n++)
  991. X        XmStringFree(s[n]);
  992. X
  993. X    dbpulldown = XmVaCreateSimplePulldownMenu(menubar, "dbase", 1,
  994. X            dbase_pulldown,
  995. X            FIX_MENUBAR
  996. X            NULL);
  997. X    XtAddCallback(dbpulldown, XmNhelpCallback,
  998. X                    help_callback, (XtPointer)"pd_dbase");
  999. X
  1000. X    sortpulldown = XmVaCreateSimplePulldownMenu(menubar, "sort", 2,
  1001. X            sort_pulldown,
  1002. X            FIX_MENUBAR
  1003. X            NULL);
  1004. X    XtAddCallback(sortpulldown, XmNhelpCallback,
  1005. X                    help_callback, (XtPointer)"pd_sort");
  1006. X
  1007. X    qpulldown = XmVaCreateSimplePulldownMenu(menubar, "query", 3,
  1008. X            query_pulldown,
  1009. X            FIX_MENUBAR
  1010. X            NULL);
  1011. X    XtAddCallback(qpulldown, XmNhelpCallback,
  1012. X                    help_callback, (XtPointer)"pd_query");
  1013. X
  1014. X    s[0] = XmStringCreateSimple("On context");
  1015. X    s[1] = XmStringCreateSimple("Current database");
  1016. X    s[2] = XmStringCreateSimple("Introduction");
  1017. X    s[3] = XmStringCreateSimple("Getting help");
  1018. X    s[4] = XmStringCreateSimple("Troubleshooting");
  1019. X    s[5] = XmStringCreateSimple("Files and programs");
  1020. X    s[6] = XmStringCreateSimple("Expression grammar");
  1021. X    s[7] = XmStringCreateSimple("Ctrl-H");
  1022. X    s[8] = XmStringCreateSimple("Ctrl-D");
  1023. X    s[9] = XmStringCreateSimple("Ctrl-G");
  1024. X    fmenu = XmVaCreateSimplePulldownMenu(menubar, "help", 4,
  1025. X            help_pulldown,
  1026. X            FIX_MENUBAR
  1027. X            XmVaPUSHBUTTON, s[0], 'C',  "Ctrl<Key>H", s[7],
  1028. X            XmVaPUSHBUTTON, s[1], 'D',  "Ctrl<Key>D", s[8],
  1029. X            XM_VA_SEPARATOR
  1030. X            XmVaPUSHBUTTON, s[2], 'I',  NULL, NULL,
  1031. X            XmVaPUSHBUTTON, s[3], 'G',  NULL, NULL,
  1032. X            XmVaPUSHBUTTON, s[4], 'T',  NULL, NULL,
  1033. X            XmVaPUSHBUTTON, s[5], 'F',  NULL, NULL,
  1034. X            XmVaPUSHBUTTON, s[6], 'E',  "Ctrl<Key>G", s[9],
  1035. X            NULL);
  1036. #ifdef XmNtearOffModel
  1037. X    XtVaSetValues(fmenu, XmNtearOffModel, XmTEAR_OFF_ENABLED, NULL);
  1038. #endif
  1039. X    for (n=0; n < 10; n++)
  1040. X        XmStringFree(s[n]);
  1041. X
  1042. X    form = XtCreateWidget("mainform", xmFormWidgetClass,
  1043. X            mainwindow, NULL, 0);
  1044. X                            /*-- search string --*/
  1045. X    n = 0;
  1046. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  1047. X    XtSetArg(args[n], XmNtopOffset,        10);            n++;
  1048. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1049. X    XtSetArg(args[n], XmNleftOffset,    OFF);            n++;
  1050. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1051. X    XtSetArg(args[n], XmNrightOffset,    OFF);            n++;
  1052. X    searchform = XtCreateManagedWidget("searchform", xmFormWidgetClass,
  1053. X            form, args, n);
  1054. X    XtAddCallback(searchform, XmNhelpCallback, help_callback,
  1055. X                            (XtPointer)"search");
  1056. X
  1057. X    n = 0;
  1058. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  1059. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1060. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1061. X    w = XtCreateManagedWidget("Search", xmPushButtonWidgetClass,
  1062. X            searchform, args, n);
  1063. X    XtAddCallback(w, XmNactivateCallback, search_callback, (XtPointer)0);
  1064. X    XtAddCallback(w, XmNhelpCallback, help_callback, (XtPointer)"search");
  1065. X
  1066. X    n = 0;
  1067. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  1068. X    XtSetArg(args[n], XmNtopOffset,        3);            n++;
  1069. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1070. X    XtSetArg(args[n], XmNbottomOffset,    3);            n++;
  1071. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  1072. X    XtSetArg(args[n], XmNrightWidget,    w);            n++;
  1073. X    XtSetArg(args[n], XmNrightOffset,    10);            n++;
  1074. X    XtSetArg(args[n], XmNarrowDirection,    XmARROW_RIGHT);        n++;
  1075. X    XtSetArg(args[n], XmNsensitive,        FALSE);            n++;
  1076. X    XtSetArg(args[n], XmNforeground,    color[COL_BACK]);    n++;
  1077. X    w = w_next = XtCreateManagedWidget("next", xmArrowButtonWidgetClass,
  1078. X            searchform, args, n);
  1079. X    XtAddCallback(w, XmNactivateCallback, search_callback, (XtPointer)1);
  1080. X    XtAddCallback(w, XmNhelpCallback, help_callback, (XtPointer)"search");
  1081. X
  1082. X    n = 0;
  1083. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  1084. X    XtSetArg(args[n], XmNtopOffset,        3);            n++;
  1085. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1086. X    XtSetArg(args[n], XmNbottomOffset,    3);            n++;
  1087. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  1088. X    XtSetArg(args[n], XmNrightWidget,    w);            n++;
  1089. X    XtSetArg(args[n], XmNarrowDirection,    XmARROW_LEFT);        n++;
  1090. X    XtSetArg(args[n], XmNsensitive,        FALSE);            n++;
  1091. X    XtSetArg(args[n], XmNforeground,    color[COL_BACK]);    n++;
  1092. X    w = w_prev = XtCreateManagedWidget("prev", xmArrowButtonWidgetClass,
  1093. X            searchform, args, n);
  1094. X    XtAddCallback(w, XmNactivateCallback, search_callback, (XtPointer)-1);
  1095. X    XtAddCallback(w, XmNhelpCallback, help_callback, (XtPointer)"search");
  1096. X
  1097. X    n = 0;
  1098. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  1099. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1100. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1101. X    XtSetArg(args[n], XmNfontList,        fontlist[FONT_HELV]);    n++;
  1102. X    w = XtCreateManagedWidget("Search:", xmLabelWidgetClass,
  1103. X            searchform, args, n);
  1104. X
  1105. X    n = 0;
  1106. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  1107. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1108. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_WIDGET);    n++;
  1109. X    XtSetArg(args[n], XmNleftWidget,    w);            n++;
  1110. X    XtSetArg(args[n], XmNleftOffset,    OFF);            n++;
  1111. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_WIDGET);    n++;
  1112. X    XtSetArg(args[n], XmNrightWidget,    w_prev);        n++;
  1113. X    XtSetArg(args[n], XmNrightOffset,    OFF);            n++;
  1114. X    XtSetArg(args[n], XmNpendingDelete,    True);            n++;
  1115. X    XtSetArg(args[n], XmNhighlightThickness,1);            n++;
  1116. X    XtSetArg(args[n], XmNbackground,    color[COL_TEXTBACK]);    n++;
  1117. X    XtSetArg(args[n], XmNfontList,        fontlist[FONT_HELV]);    n++;
  1118. X    w_search = XtCreateManagedWidget(" ", xmTextWidgetClass,
  1119. X            searchform, args, n);
  1120. X    XtAddCallback(w_search, XmNactivateCallback, search_callback, NULL);
  1121. X    XtAddCallback(w_search, XmNhelpCallback, help_callback,
  1122. X                            (XtPointer)"search");
  1123. X
  1124. X                            /*-- info line --*/
  1125. X    n = 0;
  1126. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_WIDGET);    n++;
  1127. X    XtSetArg(args[n], XmNtopWidget,        searchform);        n++;
  1128. X    XtSetArg(args[n], XmNtopOffset,        10);            n++;
  1129. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1130. X    XtSetArg(args[n], XmNleftOffset,    OFF);            n++;
  1131. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1132. X    XtSetArg(args[n], XmNrightOffset,    OFF);            n++;
  1133. X    XtSetArg(args[n], XmNalignment,     XmALIGNMENT_BEGINNING);    n++;
  1134. X    XtSetArg(args[n], XmNfontList,        fontlist[FONT_HELV]);    n++;
  1135. X    w_info = XtCreateManagedWidget(" ", xmLabelWidgetClass,
  1136. X            form, args, n);
  1137. X    XtAddCallback(w_info, XmNhelpCallback, help_callback,
  1138. X                        (XtPointer)"info");
  1139. X
  1140. X                            /*-- buttons --*/
  1141. X    n = 0;
  1142. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1143. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  1144. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1145. X    XtSetArg(args[n], XmNleftOffset,    OFF);            n++;
  1146. X    XtSetArg(args[n], XmNwidth,        40);            n++;
  1147. X    XtSetArg(args[n], XmNheight,        26);            n++;
  1148. X    XtSetArg(args[n], XmNlabelType,        XmPIXMAP);        n++;
  1149. X    XtSetArg(args[n], XmNlabelPixmap,    pixmap[PIC_LEFT]);    n++;
  1150. X    XtSetArg(args[n], XmNsensitive,        False);            n++;
  1151. X    XtSetArg(args[n], XmNhighlightThickness,1);            n++;
  1152. X    w_left = XtCreateManagedWidget("Left", xmPushButtonWidgetClass,
  1153. X            form, args, n);
  1154. X    XtAddCallback(w_left,XmNactivateCallback, pos_callback, (XtPointer)-1);
  1155. X    XtAddCallback(w_left,XmNhelpCallback, help_callback, (XtPointer)"pos");
  1156. X
  1157. X    n = 0;
  1158. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1159. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  1160. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_WIDGET);    n++;
  1161. X    XtSetArg(args[n], XmNleftWidget,    w_left);        n++;
  1162. X    XtSetArg(args[n], XmNleftOffset,    4);            n++;
  1163. X    XtSetArg(args[n], XmNwidth,        40);            n++;
  1164. X    XtSetArg(args[n], XmNheight,        26);            n++;
  1165. X    XtSetArg(args[n], XmNlabelType,        XmPIXMAP);        n++;
  1166. X    XtSetArg(args[n], XmNlabelPixmap,    pixmap[PIC_RIGHT]);    n++;
  1167. X    XtSetArg(args[n], XmNsensitive,        False);            n++;
  1168. X    XtSetArg(args[n], XmNhighlightThickness,1);            n++;
  1169. X    w_right = XtCreateManagedWidget("Right", xmPushButtonWidgetClass,
  1170. X            form, args, n);
  1171. X    XtAddCallback(w_right,XmNactivateCallback, pos_callback, (XtPointer)1);
  1172. X    XtAddCallback(w_right,XmNhelpCallback,help_callback, (XtPointer)"pos");
  1173. X
  1174. X    n = 0;
  1175. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1176. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  1177. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_WIDGET);    n++;
  1178. X    XtSetArg(args[n], XmNleftWidget,    w_right);        n++;
  1179. X    XtSetArg(args[n], XmNleftOffset,    24);            n++;
  1180. X    XtSetArg(args[n], XmNwidth,        80);            n++;
  1181. X    XtSetArg(args[n], XmNsensitive,        False);            n++;
  1182. X    XtSetArg(args[n], XmNhighlightThickness,1);            n++;
  1183. X    w_new = XtCreateManagedWidget("New", xmPushButtonWidgetClass,
  1184. X            form, args, n);
  1185. X    XtAddCallback(w_new, XmNactivateCallback, new_callback, (XtPointer)0);
  1186. X    XtAddCallback(w_new, XmNhelpCallback, help_callback, (XtPointer)"new");
  1187. X
  1188. X    n = 0;
  1189. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1190. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  1191. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_WIDGET);    n++;
  1192. X    XtSetArg(args[n], XmNleftWidget,    w_new);            n++;
  1193. X    XtSetArg(args[n], XmNleftOffset,    8);            n++;
  1194. X    XtSetArg(args[n], XmNwidth,        80);            n++;
  1195. X    XtSetArg(args[n], XmNsensitive,        False);            n++;
  1196. X    XtSetArg(args[n], XmNhighlightThickness,1);            n++;
  1197. X    w_del = XtCreateManagedWidget("Delete", xmPushButtonWidgetClass,
  1198. X            form, args, n);
  1199. X    XtAddCallback(w_del, XmNactivateCallback, del_callback, (XtPointer)0);
  1200. X    XtAddCallback(w_del, XmNhelpCallback, help_callback, (XtPointer)"del");
  1201. X
  1202. X    n = 0;
  1203. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_FORM);        n++;
  1204. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  1205. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1206. X    XtSetArg(args[n], XmNrightOffset,    OFF);            n++;
  1207. X    XtSetArg(args[n], XmNwidth,        80);            n++;
  1208. X    XtSetArg(args[n], XmNhighlightThickness,1);            n++;
  1209. X    w = XtCreateManagedWidget("Help", xmPushButtonWidgetClass,
  1210. X            form, args, n);
  1211. X    XtAddCallback(w, XmNactivateCallback,help_callback,(XtPointer)"card");
  1212. X    XtAddCallback(w, XmNhelpCallback, help_callback, (XtPointer)"card");
  1213. X
  1214. X                            /*-- summary --*/
  1215. X    n = 0;
  1216. X    XtSetArg(args[n], XmNwidth,        400);            n++;
  1217. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_WIDGET);    n++;
  1218. X    XtSetArg(args[n], XmNtopWidget,        w_info);        n++;
  1219. X    XtSetArg(args[n], XmNtopOffset,        4);            n++;
  1220. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1221. X    XtSetArg(args[n], XmNleftOffset,    OFF);            n++;
  1222. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1223. X    XtSetArg(args[n], XmNrightOffset,    OFF);            n++;
  1224. X    w = w_summary = XtCreateManagedWidget("summform", xmFormWidgetClass,
  1225. X            form, args, n);
  1226. X    XtAddCallback(w, XmNhelpCallback, help_callback, (XtPointer)"summary");
  1227. X
  1228. X                            /*-- letters --*/
  1229. X    if (pref.letters) {
  1230. X     n = 0;
  1231. X     XtSetArg(args[n], XmNtopAttachment,    XmATTACH_WIDGET);    n++;
  1232. X     XtSetArg(args[n], XmNtopWidget,    w_summary);        n++;
  1233. X     XtSetArg(args[n], XmNtopOffset,    5);            n++;
  1234. X     XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1235. X     XtSetArg(args[n], XmNleftOffset,    OFF+2);            n++;
  1236. X     XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1237. X     XtSetArg(args[n], XmNrightOffset,    OFF);            n++;
  1238. X     w = XtCreateManagedWidget("letters", xmFormWidgetClass,
  1239. X            form, args, n);
  1240. X     XtAddCallback(w, XmNhelpCallback, help_callback,(XtPointer)"letters");
  1241. X
  1242. X     for (i=0; i < 28; i++) {
  1243. X      wid = strlen_in_pixels("W", FONT_STD);
  1244. X      sprintf(buf, i < 26 ? "%c" : i==26 ? "misc" : "all", i+'A');
  1245. X      n = 0;
  1246. X      if (i == 0) {
  1247. X       XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1248. X      } else {
  1249. X       XtSetArg(args[n], XmNleftAttachment,    XmATTACH_WIDGET);    n++;
  1250. X       XtSetArg(args[n], XmNleftWidget,    w_letter[i-1]);        n++;
  1251. X      }
  1252. X      if (i < 26) {
  1253. X       XtSetArg(args[n], XmNwidth,        wid + 6);        n++;
  1254. X      }
  1255. X      XtSetArg(args[n], XmNheight,        wid + 6);        n++;
  1256. X      XtSetArg(args[n], XmNleftOffset,    0);            n++;
  1257. X      XtSetArg(args[n], XmNshadowThickness,    2);            n++;
  1258. X      XtSetArg(args[n], XmNtopAttachment,    XmATTACH_FORM);        n++;
  1259. X      XtSetArg(args[n], XmNbottomAttachment,XmATTACH_FORM);        n++;
  1260. X      XtSetArg(args[n], XmNhighlightThickness, 0);            n++;
  1261. X      w_letter[i] = XtCreateManagedWidget(buf, xmPushButtonWidgetClass,
  1262. X                    w, args, n);
  1263. X      XtAddCallback(w_letter[i], XmNactivateCallback,
  1264. X                    letter_callback, (XtPointer)i);
  1265. X      XtAddCallback(w_letter[i], XmNhelpCallback,
  1266. X                    help_callback, (XtPointer)"letters");
  1267. X     }
  1268. X    }
  1269. X                            /*-- card --*/
  1270. X    n = 0;
  1271. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_WIDGET);    n++;
  1272. X    XtSetArg(args[n], XmNtopWidget,        w);            n++;
  1273. X    XtSetArg(args[n], XmNtopOffset,        OFF);            n++;
  1274. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1275. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1276. X    w = XtCreateManagedWidget(" ", xmSeparatorWidgetClass,
  1277. X            form, args, n);
  1278. X    n = 0;
  1279. X    XtSetArg(args[n], XmNwidth,        400);            n++;
  1280. X    XtSetArg(args[n], XmNheight,        6);            n++;
  1281. X    XtSetArg(args[n], XmNtopAttachment,    XmATTACH_WIDGET);    n++;
  1282. X    XtSetArg(args[n], XmNtopWidget,        w);            n++;
  1283. X    XtSetArg(args[n], XmNtopOffset,        OFF);            n++;
  1284. X    XtSetArg(args[n], XmNbottomAttachment,    XmATTACH_WIDGET);    n++;
  1285. X    XtSetArg(args[n], XmNbottomWidget,    w_new);            n++;
  1286. X    XtSetArg(args[n], XmNbottomOffset,    8);            n++;
  1287. X    XtSetArg(args[n], XmNleftAttachment,    XmATTACH_FORM);        n++;
  1288. X    XtSetArg(args[n], XmNleftOffset,    OFF);            n++;
  1289. X    XtSetArg(args[n], XmNrightAttachment,    XmATTACH_FORM);        n++;
  1290. X    XtSetArg(args[n], XmNrightOffset,    OFF);            n++;
  1291. X    w_card = XtCreateManagedWidget("cardform", xmFormWidgetClass,
  1292. X            form, args, n);
  1293. X    XtAddCallback(w_card, XmNhelpCallback,help_callback,(XtPointer)"card");
  1294. X
  1295. X    XtManageChild(form);
  1296. X    XtManageChild(menubar);
  1297. X    create_summary_menu(curr_card, w_summary, mainwindow);
  1298. X    remake_dbase_pulldown();
  1299. X    remake_query_pulldown();
  1300. X    remake_sort_pulldown();
  1301. }
  1302. X
  1303. X
  1304. /*
  1305. X * resize the main window such that there is enough room for the summary
  1306. X * and the card. During startup, create_mainwindow() has stored the size
  1307. X * without summary and card, now add enough space for the new summary and
  1308. X * card and resize the window.
  1309. X */
  1310. X
  1311. resize_mainwindow()
  1312. {
  1313. X    Arg        args[2];
  1314. X    Dimension    xs=0, ys=0;
  1315. X
  1316. X    if (!win_ys) {
  1317. X        XtSetArg(args[0], XmNwidth,  &win_xs);
  1318. X        XtSetArg(args[1], XmNheight, &win_ys);
  1319. X        XtGetValues(mainwindow, args, 2);
  1320. X        win_ys -= 1;
  1321. X    }
  1322. X    if (curr_card && curr_card->form) {
  1323. X        xs = curr_card->form->xs + 2;
  1324. X        ys = curr_card->form->ys + 2;
  1325. X    }
  1326. X    if (win_xs > xs) xs = win_xs;
  1327. X    XtSetArg(args[0], XmNwidth,  xs + 2*2 + 2*16);
  1328. X    XtSetArg(args[1], XmNheight, win_ys + ys + 2*3);
  1329. X    XtSetValues(XtParent(mainwindow), args, 2);
  1330. }
  1331. X
  1332. X
  1333. /*
  1334. X * print some enlightening info about the database into the info line between
  1335. X * the search string and the summary. This is called whenever something
  1336. X * changes: either the database was modified, or saved (modified is turned
  1337. X * off), or a search is done.
  1338. X */
  1339. X
  1340. void print_info_line()
  1341. {
  1342. X    if (!display)
  1343. X        return;
  1344. X    if (!curr_card || !curr_card->dbase)
  1345. X        print_button(w_info, "No database");
  1346. X    else if (!curr_card->dbase->nrows)
  1347. X        print_button(w_info, "No cards");
  1348. X    else
  1349. X        print_button(w_info, "%s: %d of %d cards %s",
  1350. X                curr_card->form->name ? curr_card->form->name
  1351. X                              : "(no database)",
  1352. X                curr_card->nquery,
  1353. X                curr_card->dbase->nrows,
  1354. X                curr_card->dbase->rdonly   ? "(read only)" :
  1355. X                curr_card->dbase->modified ? "(modified)":"");
  1356. }
  1357. X
  1358. X
  1359. /*-------------------------------------------------- variable pulldowns -----*/
  1360. /*
  1361. X * Read the current directory, the ./grokdir directory, the GROKDIR directory,
  1362. X * and the preference directories, and collect all form files (*.f) and put
  1363. X * them into the Form pulldown (pulldown #1). This is, of course, a flagrant
  1364. X * violation of the Motif style guide.
  1365. X */
  1366. X
  1367. #define MAXD    200        /* no more than 200 databases in pulldown */
  1368. static char    *dbname[MAXD];    /* callback gets an index into this array */
  1369. static char    *dbpath[MAXD];    /* path where form file was found */
  1370. static Widget    dbwidget[MAXD];    /* button widgets, destroyed before remake */
  1371. X
  1372. static int append_to_dbase_pulldown(nlines, path)
  1373. X    int        nlines;        /* # of databases already in pulldown*/
  1374. X    char        *path;        /* directory name */
  1375. {
  1376. X    char        *p;        /* for removing extension */
  1377. X    DIR        *dir;        /* open directory file */
  1378. X    struct dirent    *dp;        /* one directory entry */
  1379. X    int        num=0;
  1380. X
  1381. X    path = resolve_tilde(path, 0);
  1382. X    if (!(dir = opendir(path)))
  1383. X        return(nlines);
  1384. X    while (nlines < MAXD-!num) {
  1385. X        if (!(dp = readdir(dir)))
  1386. X            break;
  1387. X        if (!(p = strrchr(dp->d_name, '.')) || strcmp(p, ".gf"))
  1388. X            continue;
  1389. X        *p = 0;
  1390. #        ifndef NOMSEP
  1391. X        if (!num++ && nlines)
  1392. X            dbwidget[nlines++] = XtCreateManagedWidget(" ",
  1393. X                xmSeparatorWidgetClass, dbpulldown, NULL, 0);
  1394. #        endif
  1395. X        dbname[nlines] = mystrdup(dp->d_name);
  1396. X        dbpath[nlines] = mystrdup(path);
  1397. X        dbwidget[nlines] = XtCreateManagedWidget(dp->d_name,
  1398. X                xmPushButtonGadgetClass, dbpulldown, NULL, 0);
  1399. X        XtAddCallback(dbwidget[nlines], XmNactivateCallback,
  1400. X                dbase_pulldown, (XtPointer)nlines);
  1401. X        nlines++;
  1402. X    }
  1403. X    (void)closedir(dir);
  1404. X    return(nlines);
  1405. }
  1406. X
  1407. X
  1408. remake_dbase_pulldown()
  1409. {
  1410. X    int        n;
  1411. X    char        path[1024];
  1412. X
  1413. X    for (n=0; n < MAXD; n++) {
  1414. X        if (dbwidget[n])
  1415. X            XtDestroyWidget(dbwidget[n]);
  1416. X        if (dbpath[n])
  1417. X            free((void *)dbpath[n]);
  1418. X        if (dbname[n])
  1419. X            free((void *)dbname[n]);
  1420. X        dbwidget[n] = 0;
  1421. X        dbname[n] = 0;
  1422. X        dbpath[n] = 0;
  1423. X    }
  1424. X    sprintf(path, "%s/grokdir", LIB);
  1425. X    n = append_to_dbase_pulldown(0, "./");
  1426. X    n = append_to_dbase_pulldown(n, "./grokdir");
  1427. X    n = append_to_dbase_pulldown(n, GROKDIR);
  1428. X    n = append_to_dbase_pulldown(n, path);
  1429. #ifdef XmNtearOffModel
  1430. X    XtVaSetValues(dbpulldown, XmNtearOffModel, XmTEAR_OFF_ENABLED, NULL);
  1431. #endif
  1432. }
  1433. X
  1434. X
  1435. /*
  1436. X * Put all the default queries in the form into the Query pulldown (pulldown
  1437. X * #3). Add a default query "All" at the top. This is yet another violation
  1438. X * of the Motif style guide. So what.
  1439. X */
  1440. X
  1441. #define MAXQ    100        /* no more than 100 queries in pulldown */
  1442. static Widget    qwidget[MAXQ];    /* button widgets, destroyed before remake */
  1443. X
  1444. remake_query_pulldown()
  1445. {
  1446. X    DQUERY        *dq;        /* current query entry */
  1447. X    int        i;        /* # of queries in pulldown */
  1448. X    int        n;        /* max # of lines in pulldown */
  1449. X
  1450. X    for (n=0; n < MAXQ; n++) {
  1451. X        if (qwidget[n])
  1452. X            XtDestroyWidget(qwidget[n]);
  1453. X        qwidget[n] = 0;
  1454. X    }
  1455. X    if (!curr_card || !curr_card->form)
  1456. X        return;
  1457. X
  1458. X    qwidget[0] = XtCreateManagedWidget("All",
  1459. X            xmPushButtonGadgetClass, qpulldown, NULL, 0);
  1460. X    XtAddCallback(qwidget[0], XmNactivateCallback,
  1461. X            query_pulldown, (XtPointer)0);
  1462. X    n = curr_card->form->nqueries > MAXQ ? MAXQ
  1463. X                         : curr_card->form->nqueries;
  1464. X    for (i=0; i < n; i++) {
  1465. X        dq = &curr_card->form->query[i];
  1466. X        if (dq->suspended || !dq->name || !dq->query)
  1467. X            continue;
  1468. X        qwidget[i+1] = XtCreateManagedWidget(dq->name,
  1469. X                xmPushButtonGadgetClass, qpulldown, NULL, 0);
  1470. X        XtAddCallback(qwidget[i+1], XmNactivateCallback,
  1471. X                query_pulldown, (XtPointer)(i+1));
  1472. X    }
  1473. #ifdef XmNtearOffModel
  1474. X    XtVaSetValues(qpulldown, XmNtearOffModel, XmTEAR_OFF_ENABLED, NULL);
  1475. #endif
  1476. }
  1477. X
  1478. X
  1479. /*
  1480. X * Put all the columns in the summary into the Sort pulldown (pulldown #2),
  1481. X * except those that have the nosort flag set.
  1482. X * What you hear weeping is the author of the Motif style guide.
  1483. X */
  1484. X
  1485. #define MAXS    100        /* no more than 100 criteria in pulldown */
  1486. static Widget    swidget[MAXS];    /* button widgets, destroyed before remake */
  1487. X
  1488. remake_sort_pulldown()
  1489. {
  1490. X    int        sort_col[MAXS];    /* column for each pulldown item */
  1491. X    char        buf[256];    /* pulldown line text */
  1492. X    register ITEM    *item;        /* scan items for sortable columns */
  1493. X    int        i;        /* item counter */
  1494. X    int        j;        /* skip redundant choice items */
  1495. X    int        n;        /* # of lines in pulldown */
  1496. X
  1497. X    for (n=0; n < MAXS; n++) {
  1498. X        if (swidget[n])
  1499. X            XtDestroyWidget(swidget[n]);
  1500. X        swidget[n] = 0;
  1501. X    }
  1502. X    if (!curr_card || !curr_card->form || !curr_card->dbase)
  1503. X        return;
  1504. X
  1505. X    for (n=i=0; i < curr_card->form->nitems; i++) {
  1506. X        item = curr_card->form->items[i];
  1507. X        if (!IN_DBASE(item->type) || item->nosort)
  1508. X            continue;
  1509. X        for (j=0; j < n; j++)
  1510. X            if (item->column == sort_col[j])
  1511. X                break;
  1512. X        if (j < n)
  1513. X            continue;
  1514. X        sprintf(buf, "by %.200s",
  1515. X            item->type == IT_CHOICE ? item->name : item->label);
  1516. X        if (buf[j = strlen(buf)-1] == ':')
  1517. X            buf[j] = 0;
  1518. X        swidget[n] = XtCreateManagedWidget(buf,
  1519. X                xmPushButtonGadgetClass, sortpulldown, NULL,0);
  1520. X        XtAddCallback(swidget[n], XmNactivateCallback,
  1521. X                sort_pulldown, (XtPointer)item->column);
  1522. X        sort_col[n++] = item->column;
  1523. X    }
  1524. #ifdef XmNtearOffModel
  1525. X    XtVaSetValues(sortpulldown, XmNtearOffModel, XmTEAR_OFF_ENABLED,NULL);
  1526. #endif
  1527. }
  1528. X
  1529. X
  1530. /*-------------------------------------------------- switch databases -------*/
  1531. /*
  1532. X * switch main window to new database. This happens on startup if a form
  1533. X * name is given on the command line, and whenever a new form name is chosen
  1534. X * from the database pulldown. ".gf" is appended to formname if necessary. If
  1535. X * formname == 0, kill the current form and don't switch to a new one. Sort
  1536. X * the new database by the default sort criterion if there is one.
  1537. X */
  1538. X
  1539. void switch_form(formname)
  1540. X    char        *formname;    /* new form name */
  1541. {
  1542. X    char        name[1024], *p;    /* capitalized formname */
  1543. X    Arg        args[5];
  1544. X    int        i;
  1545. X
  1546. X    if (curr_card) {
  1547. X        if (prev_form)
  1548. X            free(prev_form);
  1549. X        prev_form = 0;
  1550. X        if (curr_card->form)
  1551. X            prev_form = mystrdup(curr_card->form->name);
  1552. X        destroy_card_menu(curr_card);
  1553. X        if (curr_card->dbase) {
  1554. X            if (curr_card->dbase->modified &&
  1555. X               !curr_card->dbase->rdonly &&
  1556. X               !curr_card->form->rdonly)
  1557. X                if (!write_dbase(curr_card->dbase,
  1558. X                         curr_card->form))
  1559. X                    return;
  1560. X            dbase_delete(curr_card->dbase);
  1561. X            free((void *)curr_card->dbase);
  1562. X        }
  1563. X        if (curr_card->form) {
  1564. X            form_delete(curr_card->form);
  1565. X            free((void *)curr_card->form);
  1566. X        }
  1567. X        free((void *)curr_card);
  1568. X        curr_card = 0;
  1569. X    }
  1570. X    if (formname && *formname) {
  1571. X        FORM  *form  = form_create();
  1572. X        DBASE *dbase = dbase_create();
  1573. X        if (read_form(form, formname))
  1574. X            (void)read_dbase(dbase, form,
  1575. X                    form->dbase ? form->dbase : formname);
  1576. X
  1577. X        curr_card = create_card_menu(form, dbase, w_card);
  1578. X        curr_card->form  = form;
  1579. X        curr_card->dbase = dbase;
  1580. X        curr_card->row   = 0;
  1581. X        col_sorted_by    = 0;
  1582. X        for (i=0; i < form->nitems; i++)
  1583. X            if (form->items[i]->defsort) {
  1584. X                dbase_sort(curr_card, form->items[i]->column);
  1585. X                break;
  1586. X            }
  1587. X        if (form->autoquery >= 0 && form->autoquery < form->nqueries)
  1588. X            query_any(curr_card,
  1589. X                  form->query[form->autoquery].query);
  1590. X        else
  1591. X            query_all(curr_card);
  1592. X        create_summary_menu(curr_card, w_summary, mainwindow);
  1593. X
  1594. X        strcpy(name, formname);
  1595. X        if (*name >= 'a' && *name <= 'z')
  1596. X            *name += 'A' - 'a';
  1597. X        if (p = strrchr(name, '.'))
  1598. X            *p = 0;
  1599. X        if (p = strrchr(name, '/'))
  1600. X            p++;
  1601. X        else
  1602. X            p = name;
  1603. X        if (toplevel) {
  1604. X            XtVaSetValues(toplevel, XmNiconName, p, NULL);
  1605. X            fillout_card(curr_card, FALSE);
  1606. X        }
  1607. X    } else
  1608. X        if (toplevel)
  1609. X            XtVaSetValues(toplevel, XmNiconName, "None", NULL);
  1610. X
  1611. X    if (toplevel) {
  1612. X        XtSetArg(args[0], XmNsensitive, formname != 0);
  1613. X        XtSetValues(w_left,  args, 1);
  1614. X        XtSetValues(w_right, args, 1);
  1615. X        XtSetValues(w_del,   args, 1);
  1616. X        XtSetValues(w_new,   args, 1);
  1617. X
  1618. X        remake_query_pulldown();
  1619. X        remake_sort_pulldown();
  1620. X        resize_mainwindow();
  1621. X        if (curr_card && curr_card->dbase)
  1622. X            curr_card->dbase->modified = FALSE;
  1623. X        print_info_line();
  1624. X    }
  1625. }
  1626. X
  1627. X
  1628. /*-------------------------------------------------- callbacks --------------*/
  1629. /*
  1630. X * some item in one of the menu bar pulldowns was pressed. All of these
  1631. X * routines are direct X callbacks.
  1632. X */
  1633. X
  1634. static void rambo_quit() { exit(0); }
  1635. X
  1636. /*ARGSUSED*/
  1637. static void file_pulldown(widget, item, data)
  1638. X    Widget                widget;
  1639. X    int                item;
  1640. X    XmToggleButtonCallbackStruct    *data;
  1641. {
  1642. X    card_readback_texts(curr_card, -1);
  1643. X    switch (item) {
  1644. X      case 0:                        /* print */
  1645. X        create_print_popup();
  1646. X        break;
  1647. X
  1648. X      case 1:                        /* preference*/
  1649. X        create_preference_popup();
  1650. X        break;
  1651. X
  1652. X      case 3:                        /* about */
  1653. X        create_about_popup();
  1654. X        break;
  1655. X
  1656. X      case 4:                        /* save */
  1657. X        if (curr_card && curr_card->form && curr_card->dbase)
  1658. X            if (curr_card->form->rdonly)
  1659. X                create_error_popup(mainwindow, 0,
  1660. X                   "Database is marked read-only in the form");
  1661. X            else
  1662. X                (void)write_dbase(curr_card->dbase,
  1663. X                          curr_card->form);
  1664. X        else
  1665. X            create_error_popup(mainwindow,0,"No database to save");
  1666. X        print_info_line();
  1667. X        break;
  1668. X
  1669. X      case 5:                        /* quit */
  1670. X        if (curr_card &&  curr_card->dbase
  1671. X                  &&  curr_card->dbase->modified
  1672. X                  && !curr_card->form->rdonly
  1673. X                  && !write_dbase(curr_card->dbase,
  1674. X                        curr_card->form))
  1675. X            break;
  1676. X        exit(0);
  1677. X
  1678. X      case 6:                        /* rambo quit*/
  1679. X        if (curr_card &&  curr_card->dbase
  1680. X                  && !curr_card->dbase->rdonly
  1681. X                  &&  curr_card->dbase->modified
  1682. X                  && !curr_card->form->rdonly)
  1683. X            create_query_popup(mainwindow, rambo_quit, "rambo",
  1684. X                "OK to discard changes and quit?");
  1685. X        else
  1686. X            exit(0);
  1687. X    }
  1688. }
  1689. X
  1690. X
  1691. /*ARGSUSED*/
  1692. static void newform_pulldown(widget, item, data)
  1693. X    Widget                widget;
  1694. X    int                item;
  1695. X    XmToggleButtonCallbackStruct    *data;
  1696. {
  1697. X    card_readback_texts(curr_card, -1);
  1698. X    switch (item) {
  1699. X      case 0:                        /* current */
  1700. X        if (curr_card && curr_card->form) {
  1701. X            if (curr_card->dbase        &&
  1702. X               !curr_card->dbase->rdonly    &&
  1703. X                curr_card->dbase->modified    &&
  1704. X               !curr_card->form->rdonly    &&
  1705. X               !write_dbase(curr_card->dbase,
  1706. X                    curr_card->form))
  1707. X                        return;
  1708. X            create_formedit_window(curr_card->form, FALSE, FALSE);
  1709. X        } else
  1710. X            create_error_popup(toplevel, 0,
  1711. X             "Please choose database to edit\nfrom Database pulldown");
  1712. X        break;
  1713. X
  1714. X      case 1:                        /* new */
  1715. X        switch_form(0);
  1716. X        create_formedit_window(0, FALSE, TRUE);
  1717. X        break;
  1718. X
  1719. X      case 2:                        /* clone */
  1720. X        if (curr_card && curr_card->form) {
  1721. X            if (curr_card->dbase        &&
  1722. X               !curr_card->dbase->rdonly    &&
  1723. X                curr_card->dbase->modified    &&
  1724. X               !curr_card->form->rdonly    &&
  1725. X               !write_dbase(curr_card->dbase,
  1726. X                    curr_card->form))
  1727. X                        return;
  1728. X            create_formedit_window(curr_card->form, TRUE, TRUE);
  1729. X        } else
  1730. X            create_error_popup(toplevel, 0,
  1731. X            "Please choose database from Database pulldown first");
  1732. X        break;
  1733. X    }
  1734. }
  1735. X
  1736. X
  1737. /*ARGSUSED*/
  1738. static void help_pulldown(widget, item, data)
  1739. X    Widget                widget;
  1740. X    int                item;
  1741. X    XmToggleButtonCallbackStruct    *data;
  1742. {
  1743. X    Cursor                cursor;
  1744. X    Widget                w;
  1745. X
  1746. X    switch (item) {
  1747. X      case 0:                        /* context */
  1748. X        cursor = XCreateFontCursor(display, XC_question_arrow);
  1749. X        if (w = XmTrackingLocate(mainwindow, cursor, False)) {
  1750. X            data->reason = XmCR_HELP;
  1751. X            XtCallCallbacks(w, XmNhelpCallback, &data);
  1752. X        }
  1753. X        XFreeCursor(display, cursor);
  1754. X        break;
  1755. X
  1756. X      case 1:                        /* database */
  1757. X        create_dbase_info_popup(curr_card);
  1758. X        break;
  1759. X
  1760. X      case 2:                        /* intro */
  1761. X        help_callback(mainwindow, "intro");
  1762. X        break;
  1763. X
  1764. X      case 3:                        /* help */
  1765. X        help_callback(mainwindow, "help");
  1766. X        break;
  1767. X
  1768. X      case 4:                        /* trouble */
  1769. X        help_callback(mainwindow, "trouble");
  1770. X        break;
  1771. X
  1772. X      case 5:                        /* files */
  1773. X        help_callback(mainwindow, "files");
  1774. X        break;
  1775. X
  1776. X      case 6:                        /* expr */
  1777. X        help_callback(mainwindow, "grammar");
  1778. X        break;
  1779. X    }
  1780. }
  1781. X
  1782. X
  1783. /*ARGSUSED*/
  1784. static void dbase_pulldown(widget, item, data)
  1785. X    Widget                widget;
  1786. X    int                item;
  1787. X    XmToggleButtonCallbackStruct    *data;
  1788. {
  1789. X    char                path[1024];
  1790. X
  1791. X    card_readback_texts(curr_card, -1);
  1792. X    sprintf(path, "%s/%s.gf", dbpath[item], dbname[item]);
  1793. X    switch_form(path);
  1794. X    remake_dbase_pulldown();
  1795. }
  1796. X
  1797. X
  1798. /*ARGSUSED*/
  1799. static void query_pulldown(widget, item, data)
  1800. X    Widget                widget;
  1801. X    int                item;
  1802. X    XmToggleButtonCallbackStruct    *data;
  1803. {
  1804. X    print_info_line();
  1805. X    if (!curr_card || !curr_card->dbase || !curr_card->dbase->nrows)
  1806. X        return;
  1807. X    card_readback_texts(curr_card, -1);
  1808. X    if (item == 0)
  1809. X        query_all(curr_card);
  1810. X
  1811. X    else if (*curr_card->form->query[item-1].query == '/') {
  1812. X        char *query = curr_card->form->query[item-1].query;
  1813. X        char *string = XtMalloc(strlen(query));
  1814. X        strcpy(string, query+1);
  1815. X        append_search_string(string);
  1816. X        query_search(curr_card, query+1);
  1817. X    } else {
  1818. X        char *query = curr_card->form->query[item-1].query;
  1819. X        if (pref.query2search) {
  1820. X            char *string = XtMalloc(strlen(query)+1);
  1821. X            strcpy(string, query);
  1822. X            append_search_string(string);
  1823. X        }
  1824. X        query_eval(curr_card, query);
  1825. X    }
  1826. X    create_summary_menu(curr_card, w_summary, mainwindow);
  1827. X
  1828. X    curr_card->row = curr_card->query ? curr_card->query[0]
  1829. X                      : curr_card->dbase->nrows;
  1830. X    fillout_card(curr_card, FALSE);
  1831. }
  1832. X
  1833. X
  1834. /*ARGSUSED*/
  1835. static void sort_pulldown(widget, item, data)
  1836. X    Widget                widget;
  1837. X    int                item;
  1838. X    XmToggleButtonCallbackStruct    *data;
  1839. {
  1840. X    card_readback_texts(curr_card, -1);
  1841. X    dbase_sort(curr_card, item);
  1842. X    create_summary_menu(curr_card, w_summary, mainwindow);
  1843. X    curr_card->row = curr_card->query ? curr_card->query[0]
  1844. X                      : curr_card->dbase->nrows;
  1845. X    fillout_card(curr_card, FALSE);
  1846. }
  1847. X
  1848. X
  1849. /*
  1850. X * search for a search string, or for matching expressions. Put matching
  1851. X * cards into the summary. The string is an expression if it begins with
  1852. X * '(' or '{', or a search string otherwise. This is called from the
  1853. X * switch statement in expressions too.
  1854. X */
  1855. X
  1856. /*ARGSUSED*/
  1857. search_cards(card, string)
  1858. X    CARD                *card;
  1859. X    char                *string;
  1860. {
  1861. X    char                *search_string;
  1862. X    char                *eval;
  1863. X
  1864. X    if (!string || !*string)
  1865. X        return;
  1866. X    print_info_line();
  1867. X    card_readback_texts(card, -1);
  1868. X    if (!card || !card->dbase || !card->dbase->nrows)
  1869. X        return;
  1870. X    query_any(card, string);
  1871. X    create_summary_menu(card, w_summary, mainwindow);
  1872. X    card->row = card->query ? card->query[0] : card->dbase->nrows;
  1873. X    fillout_card(card, FALSE);
  1874. }
  1875. X
  1876. X
  1877. /*
  1878. X * Searches. When a search string is entered, read it from the button and
  1879. X * search for it. The arrows put a string from the history array into the
  1880. X * button, where it can be searched for. The query pulldown can append a
  1881. X * string to the history if pref.query2search is on.
  1882. X */
  1883. X
  1884. static char    *history[NHIST];
  1885. static int    s_curr, s_offs;
  1886. X
  1887. /*ARGSUSED*/
  1888. static void search_callback(widget, inc, data)
  1889. X    Widget                widget;
  1890. X    int                inc;
  1891. X    XmToggleButtonCallbackStruct    *data;
  1892. {
  1893. X    if (inc) {
  1894. X        int o = s_offs + inc;
  1895. X        if (o > -NHIST && o <= 0 && history[(s_curr + o) % NHIST]) {
  1896. X            s_offs = o;
  1897. X            print_text_button(w_search,
  1898. X                    history[(s_curr + o + NHIST) % NHIST]);
  1899. X        }
  1900. X        append_search_string(0);
  1901. X    } else {
  1902. X        char *string = XmTextGetString(w_search);
  1903. X        search_cards(curr_card, string);
  1904. X        append_search_string(string);
  1905. X    }
  1906. }
  1907. X
  1908. append_search_string(text)
  1909. X    XmString    text;
  1910. {
  1911. X    Arg        arg;
  1912. X
  1913. X    if (text) {
  1914. X        print_text_button(w_search, text);
  1915. X        s_offs = 0;
  1916. X        if (history[s_curr] && *history[s_curr]
  1917. X                    && strcmp(history[s_curr], text))
  1918. X            s_curr = (s_curr + 1) % NHIST;
  1919. X        if (history[s_curr])
  1920. X            XtFree(history[s_curr]);
  1921. X        history[s_curr] = text;
  1922. X    }
  1923. X    XtSetArg(arg, XmNsensitive, s_offs < 0);
  1924. X    XtSetValues(w_next, &arg, 1);
  1925. X    XtSetArg(arg, XmNsensitive, s_offs > -NHIST+1 &&
  1926. X                history[(s_curr + s_offs + NHIST -1) % NHIST]);
  1927. X    XtSetValues(w_prev, &arg, 1);
  1928. }
  1929. X
  1930. X
  1931. /*
  1932. X * One of the letter buttons (a..z, misc, all) was pressed. Do the appropriate
  1933. X * search and display the result in the summary.
  1934. X */
  1935. X
  1936. /*ARGSUSED*/
  1937. static void letter_callback(widget, letter, cbs)
  1938. X    Widget                widget;
  1939. X    int                letter;
  1940. X    XmToggleButtonCallbackStruct    *cbs;
  1941. {
  1942. X    if (!curr_card || !curr_card->dbase || !curr_card->dbase->nrows)
  1943. X        return;
  1944. X    card_readback_texts(curr_card, -1);
  1945. X    query_letter(curr_card, letter);
  1946. X    create_summary_menu(curr_card, w_summary, mainwindow);
  1947. X    curr_card->row = curr_card->query ? curr_card->query[0]
  1948. X                      : curr_card->dbase->nrows;
  1949. X    fillout_card(curr_card, FALSE);
  1950. }
  1951. X
  1952. X
  1953. /*
  1954. X * go forward or backward in the summary list if there is one. If there is
  1955. X * no summary, we must be adding cards and the user wants to see previously
  1956. X * added cards; step in the raw database in this case.
  1957. X */
  1958. X
  1959. /*ARGSUSED*/
  1960. static void pos_callback(widget, inc, data)
  1961. X    Widget                widget;
  1962. X    int                inc;
  1963. X    XmToggleButtonCallbackStruct    *data;
  1964. {
  1965. X    register CARD            *card = curr_card;
  1966. X
  1967. X    card_readback_texts(curr_card, -1);
  1968. X    if (card->qcurr + inc >= 0 &&
  1969. X        card->qcurr + inc <  card->nquery) {
  1970. X        card->qcurr += inc;
  1971. X        card->row    = card->query[card->qcurr];
  1972. X        fillout_card(card, FALSE);
  1973. X        scroll_summary(card);
  1974. X
  1975. X    } else if (card->nquery == 0 && card->row + inc >= 0
  1976. X                     && card->row + inc <  card->dbase->nrows){
  1977. X        card->row += inc;
  1978. X        fillout_card(card, FALSE);
  1979. X    }
  1980. }
  1981. X
  1982. X
  1983. /*
  1984. X * add a new card to the database. Since we don't know whether the new card
  1985. X * will be part of the summary when it is finished, remove the summary first.
  1986. X * When finished, find the first text input item and put the cursor into it.
  1987. X */
  1988. X
  1989. /*ARGSUSED*/
  1990. static void new_callback(widget, null, cbs)
  1991. X    Widget                widget;
  1992. X    XtPointer            null;
  1993. X    XmToggleButtonCallbackStruct    *cbs;
  1994. {
  1995. X    register CARD            *card = curr_card;
  1996. X    register ITEM            *item;
  1997. X    register DBASE            *dbase = card->dbase;
  1998. X    register char            **data;
  1999. X    int                i;
  2000. X
  2001. X    card_readback_texts(card, -1);
  2002. X    if (dbase_addrow(&card->row, dbase)) {
  2003. X        if (!dbase_prune_columns(dbase, card->form)) {
  2004. X            dbase_delrow(card->row, dbase);
  2005. X            card->row = dbase->nrows;
  2006. X
  2007. X        } else for (i=0; i < card->form->nitems; i++, item++) {
  2008. X            item = card->form->items[i];
  2009. X            if (IN_DBASE(item->type) && item->idefault) {
  2010. X                data = &dbase->data[card->row * dbase->ncolumns
  2011. X                            + item->column];
  2012. X                *data = evaluate(card, item->idefault);
  2013. SHAR_EOF
  2014. true || echo 'restore of mainwin.c failed'
  2015. fi
  2016. echo 'End of grok part 5'
  2017. echo 'File mainwin.c is continued in part 6'
  2018. echo 6 > _shar_seq_.tmp
  2019. exit 0
  2020. -- 
  2021.  
  2022. --
  2023. Thomas Driemeyer       thomas@bitrot.in-berlin.de       voice: +49 30 8924936
  2024.                    Schweidnitzer Str. 6, 10709 Berlin
  2025.