2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: template.c /main/6 1999/09/20 15:48:19 mgreess $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company
26 * (c) Copyright 1993, 1994 International Business Machines Corp.
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
28 * (c) Copyright 1993, 1994 Novell, Inc.
35 * Example code for typical Dt application
37 * Simple spray-can drawing tool
40 #include <X11/IntrinsicP.h>
41 #include <X11/CoreP.h>
46 #include <Dt/HelpDialog.h>
49 /* default brush - used when the brush bitmap file is not found at run-time. */
50 #include "default_brush.bm"
52 /* Portability for catopen */
53 #if !defined(NL_CAT_LOCALE)
54 #define NL_CAT_LOCALE 0
58 #define ApplicationClass "Template"
59 #define MessageCatalog "template.cat"
60 #define HelpVolume "template"
61 #define HelpTopic "_hometopic"
62 #define IconPixmap "template_icon.pm"
63 #define IconMask "template_icon_m.bm"
64 #define Suffix ".template"
65 #define SuffixLength 9
66 #define UnnamedFile "unnamed.template"
67 #define SearchPattern "*.template"
68 #define DataType "TemplateData"
69 #define ToolTalkPType "DT_Example_Template"
70 #define FileSignature "@template@\n"
74 typedef struct _WindowData {
81 char *name; /* NULL if no file */
82 struct _WindowData *next;
85 static XtAppContext appContext;
86 static nl_catd msgCatalog;
87 static Widget appShell;
88 static WindowData *windowList = NULL;
89 static XContext wdContext;
90 static Atom WM_DELETE_WINDOW;
91 static Atom WM_SAVE_YOURSELF;
92 static char *appnameString;
93 static char *separatorString;
94 static char *untitledString;
96 static char *programName;
101 static Tt_pattern *ttpat;
102 static Tt_status ttrc;
103 static Tt_message HandleTtMedia(Tt_message, void *, Tttk_op, Tt_status,
104 unsigned char *, int, char *, char *);
106 #define DrawingTranslations "#replace\
107 <Btn1Down>: DrawingAreaInput()\n\
108 <Btn1Motion>: DrawingAreaInput()"
110 static void ClearCb(Widget, XtPointer, XtPointer);
111 static void HelpCb(Widget, XtPointer, XtPointer);
112 static void NewCb(Widget, XtPointer, XtPointer);
113 static void OpenCb(Widget, XtPointer, XtPointer);
114 static void OpenOkCb(Widget, XtPointer, XtPointer);
115 static void SaveCb(Widget, XtPointer, XtPointer);
116 static void SaveOkCb(Widget, XtPointer, XtPointer);
117 static void PrintCb(Widget, XtPointer, XtPointer);
118 static void ExitCb(Widget, XtPointer, XtPointer);
119 static void ExposeCb(Widget, XtPointer, XtPointer);
120 static void InputCb(Widget, XtPointer, XtPointer);
121 static void DropTransferCb(Widget, XtPointer, XtPointer);
122 static void SaveSessionCb(Widget, XtPointer, XtPointer);
125 LOAD_EMPTY, LOAD_FILE, LOAD_BUFFER
128 static void Fatal(char*);
129 static void ReallyExit(int);
130 static void SetTitle(Widget,char*);
131 static Boolean NewWindow(LoadType,char*,int);
132 static WindowData *NewData(void);
133 static void AssocData(WindowData*,Widget);
134 static WindowData *FindData(Widget);
135 static void DestroyData(WindowData*);
136 static Boolean LoadFile(WindowData*,char*);
137 static Boolean LoadBuffer(WindowData*,void*,int);
138 static void FreeData(WindowData*);
139 static void PrintData(WindowData*);
140 static void AddPoint(WindowData*, int, int);
141 static void DrawPoint(Widget, int, int);
142 static char* AppendString(char*,char*);
144 static XtCallbackRec DropTransferCbList[] = {
145 { DropTransferCb, NULL},
149 static XrmOptionDescRec optionTable[] = {
150 {"-print", ".printMode", XrmoptionIsArg, NULL},
151 {"-server", ".serverMode", XrmoptionIsArg, NULL},
159 static XtResource appResources[] = {
160 { "printMode", "PrintMode", XtRString, sizeof(String),
161 XtOffsetOf(appResourceRec, printMode), XtRString, NULL },
162 { "serverMode", "ServerMode", XtRString, sizeof(String),
163 XtOffsetOf(appResourceRec, serverMode), XtRString, NULL },
166 main(int argc, char **argv)
169 appResourceRec argvals;
170 char *errfmt, *errmsg, *statmsg;
173 programName = strrchr(argv[0], '/');
174 if (programName == NULL)
175 programName = argv[0];
179 XtSetLanguageProc(NULL, NULL, NULL);
181 appShell = XtAppInitialize(&appContext, ApplicationClass,
182 optionTable, XtNumber(optionTable),
183 &argc, argv, NULL, NULL, 0);
185 msgCatalog = catopen(MessageCatalog, NL_CAT_LOCALE);
187 XtGetApplicationResources(appShell, &argvals,
188 appResources, XtNumber(appResources),
191 wdContext = XUniqueContext();
193 WM_DELETE_WINDOW = XmInternAtom(XtDisplay(appShell), "WM_DELETE_WINDOW",
195 WM_SAVE_YOURSELF = XmInternAtom(XtDisplay(appShell), "WM_SAVE_YOURSELF",
198 appnameString = catgets(msgCatalog, 1, 1, "Template");
199 separatorString = catgets(msgCatalog, 1, 5, " - ");
200 untitledString = catgets(msgCatalog, 1, 6, "(untitled)");
202 if (argvals.printMode != NULL) {
203 /* Load up each file and print it, then exit */
204 WindowData *wd = NewData();
205 for (i = 1; i < argc; ++i) {
206 if (LoadFile(wd, argv[i]))
210 catgets(msgCatalog, 1, 10, "template: can't open %s\n"),
217 /* Initialize Data Typing and ToolTalk */
219 DtDtsLoadDataTypes();
221 procid = ttdt_open(&ttfd, appnameString, "CDE", "1.0", True);
222 if ((ttrc = tt_ptr_error(procid)) != TT_OK) {
223 errfmt = catgets(msgCatalog, 1, 7, "ttdt_open failed:\n%s");
224 statmsg = tt_status_message(ttrc);
225 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
226 sprintf(errmsg, errfmt, statmsg);
232 ttrc = ttmedia_ptype_declare(ToolTalkPType, 0, HandleTtMedia,
234 if (tt_is_err(ttrc)) {
235 errfmt = catgets(msgCatalog, 1, 8, "ttmedia_ptype_declare failed:\n%s");
236 statmsg = tt_status_message(status);
237 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
238 sprintf(errmsg, errfmt, statmsg);
244 ttpat = ttdt_session_join(NULL, NULL, NULL, NULL, True);
245 if ((ttrc = tt_ptr_error(ttpat)) != TT_OK) {
246 errfmt = catgets(msgCatalog, 1, 9, "ttdt_session_join failed:\n%s");
247 statmsg = tt_status_message(status);
248 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
249 sprintf(errmsg, errfmt, statmsg);
255 XtAppAddInput(appContext, ttfd, (XtPointer)XtInputReadMask,
256 tttk_Xt_input_handler, NULL);
258 if (argvals.serverMode != NULL) {
260 * We're in server mode. Thus do nothing until requested to do so
263 } else if (argc < 2) {
264 /* No files given, so put up an untitled window. */
265 (void) NewWindow(LOAD_EMPTY, NULL, 0);
267 /* Load each file into its own window. */
268 for (i = 1; i < argc; ++i)
269 (void) NewWindow(LOAD_FILE, argv[i], 0);
273 * Start the GUI. Note that we explicitly do not realize the appShell
274 * widget, since it is the unmapped parent of all of the top-level shells
278 XtAppMainLoop(appContext);
284 * Close ToolTalk and exit.
286 static void ReallyExit(int rc)
294 * Issue an error message and exit.
296 static void Fatal(char *msg)
298 fprintf(stderr, "%s: %s\n", programName, msg);
304 * Create a new top-level window. If loadtype is LOAD_EMPTY, name_or_buf and
305 * len are ignored. If loadtype is LOAD_FILE, name_or_buf should point to the
306 * name of the file to load, and len is ignored. If loadtype is LOAD_BUFFER,
307 * name_or_buf is a pointer to the data buffer and len is its length.
310 NewWindow(LoadType loadtype, char *name_or_buf, int len)
312 Widget toplevel, mainWindow, menuBar, frame1, frame2,
313 drawingArea, pd, cb, pb;
315 XmString labelString;
316 XtTranslations drawingTranslations;
327 toplevel = XtCreatePopupShell("foo", topLevelShellWidgetClass,
330 /* Create main window */
333 mainWindow = XmCreateMainWindow(toplevel, "mainWindow", args, n);
334 XtManageChild(mainWindow);
336 /* Set window manager title and icon */
338 XtVaGetValues(mainWindow, XmNforeground, &fg, XmNbackground, &bg, NULL);
339 iconPixmap = XmGetPixmap(XtScreen(toplevel), IconPixmap, fg, bg);
340 iconMask = XmGetPixmapByDepth(XtScreen(toplevel), IconMask, 1, 0, 1);
341 XtVaSetValues(toplevel,
342 XmNiconName, appnameString,
343 XmNiconPixmap, iconPixmap,
344 XmNiconMask, iconMask,
349 menuBar = XmCreateMenuBar(mainWindow, "menuBar", NULL, 0);
350 XtManageChild(menuBar);
354 pd = XmCreatePulldownMenu(menuBar, "fileMenu", NULL, 0);
356 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 1, "File"));
358 XtSetArg(args[n], XmNlabelString, labelString); n++;
359 XtSetArg(args[n], XmNmnemonic, 'F'); n++;
360 XtSetArg(args[n], XmNsubMenuId, pd); n++;
361 cb = XmCreateCascadeButton(menuBar, "fileCascade", args, n);
363 XmStringFree(labelString);
365 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 9, "New..."));
367 XtSetArg(args[n], XmNlabelString, labelString); n++;
368 XtSetArg(args[n], XmNmnemonic, 'N'); n++;
369 pb = XmCreatePushButton(pd, "newButton", args, n);
371 XtAddCallback(pb, XmNactivateCallback, NewCb, NULL);
372 XmStringFree(labelString);
374 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 2, "Open..."));
376 XtSetArg(args[n], XmNlabelString, labelString); n++;
377 XtSetArg(args[n], XmNmnemonic, 'O'); n++;
378 pb = XmCreatePushButton(pd, "openButton", args, n);
380 XtAddCallback(pb, XmNactivateCallback, OpenCb, (XtPointer)wd);
381 XmStringFree(labelString);
383 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 3,
386 XtSetArg(args[n], XmNlabelString, labelString); n++;
387 XtSetArg(args[n], XmNmnemonic, 'S'); n++;
388 pb = XmCreatePushButton(pd, "saveButton", args, n);
390 XtAddCallback(pb, XmNactivateCallback, SaveCb, (XtPointer)wd);
391 XmStringFree(labelString);
393 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 4, "Print"));
395 XtSetArg(args[n], XmNlabelString, labelString); n++;
396 XtSetArg(args[n], XmNmnemonic, 'P'); n++;
397 pb = XmCreatePushButton(pd, "printButton", args, n);
399 XtAddCallback(pb, XmNactivateCallback, PrintCb, (XtPointer)wd);
400 XmStringFree(labelString);
402 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 5, "Clear"));
404 XtSetArg(args[n], XmNlabelString, labelString); n++;
405 XtSetArg(args[n], XmNmnemonic, 'C'); n++;
406 pb = XmCreatePushButton(pd, "clearButton", args, n);
408 XtAddCallback(pb, XmNactivateCallback, ClearCb, (XtPointer)wd);
409 XmStringFree(labelString);
411 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 6, "Exit"));
413 XtSetArg(args[n], XmNlabelString, labelString); n++;
414 XtSetArg(args[n], XmNmnemonic, 'E'); n++;
415 pb = XmCreatePushButton(pd, "exitButton", args, n);
417 XtAddCallback(pb, XmNactivateCallback, ExitCb, (XtPointer)wd);
418 XmStringFree(labelString);
422 pd = XmCreatePulldownMenu(menuBar, "helpMenu", NULL, 0);
424 labelString = XmStringCreateLocalized(catgets(msgCatalog, 2, 7, "Help"));
426 XtSetArg(args[n], XmNlabelString, labelString); n++;
427 XtSetArg(args[n], XmNmnemonic, 'H'); n++;
428 XtSetArg(args[n], XmNsubMenuId, pd); n++;
429 cb = XmCreateCascadeButton(menuBar, "helpCascade", args, n);
431 XmStringFree(labelString);
433 XtVaSetValues(menuBar, XmNmenuHelpWidget, cb, NULL);
435 labelString = XmStringCreateLocalized(catgets(msgCatalog,2,8, "Overview..."));
437 XtSetArg(args[n], XmNlabelString, labelString); n++;
438 XtSetArg(args[n], XmNmnemonic, 'O'); n++;
439 pb = XmCreatePushButton(pd, "helpButton", args, n);
441 XtAddCallback(pb, XmNactivateCallback, HelpCb, NULL);
442 XmStringFree(labelString);
444 /* Drawing work area */
447 XtSetArg(args[n], XmNshadowThickness, 0); n++;
448 XtSetArg(args[n], XmNmarginWidth, 20); n++;
449 XtSetArg(args[n], XmNmarginHeight, 20); n++;
450 frame1 = XmCreateFrame(mainWindow, "frame1", args, n);
451 XtManageChild(frame1);
454 XtSetArg(args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
455 frame2 = XmCreateFrame(frame1, "frame2", args, n);
456 XtManageChild(frame2);
458 drawingTranslations = XtParseTranslationTable(DrawingTranslations);
461 XtSetArg(args[n], XmNunitType, Xm100TH_MILLIMETERS); n++;
462 XtSetArg(args[n], XmNwidth, 12000); n++;
463 XtSetArg(args[n], XmNheight, 12000); n++;
464 XtSetArg(args[n], XmNtranslations, drawingTranslations); n++;
465 drawingArea = XmCreateDrawingArea(frame2, "drawingArea", args, n);
466 XtManageChild(drawingArea);
467 XtAddCallback(drawingArea, XmNexposeCallback, ExposeCb, NULL);
468 XtAddCallback(drawingArea, XmNinputCallback, InputCb, NULL);
470 DtDndDropRegister(drawingArea,
471 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
472 XmDROP_COPY, DropTransferCbList, NULL, 0);
474 XmAddWMProtocolCallback(toplevel, WM_DELETE_WINDOW, ExitCb, (XtPointer)wd);
475 XmAddWMProtocolCallback(toplevel, WM_SAVE_YOURSELF, SaveSessionCb,
478 XtRealizeWidget(toplevel);
479 XtPopup(toplevel, XtGrabNone);
481 AssocData(wd, toplevel);
485 SetTitle(toplevel, NULL);
488 return LoadFile(wd, name_or_buf);
490 return LoadBuffer(wd, name_or_buf, len);
497 * Display the help system. On the first call, create the help widget.
500 static void HelpCb(Widget w, XtPointer cd, XtPointer cb)
502 static Widget helpDialog = NULL;
504 if (helpDialog == NULL) {
510 XtSetArg(args[n], DtNhelpVolume, HelpVolume); n++;
511 XtSetArg(args[n], DtNhelpType, DtHELP_TYPE_TOPIC); n++;
512 XtSetArg(args[n], DtNlocationId, HelpTopic); n++;
513 helpDialog = DtCreateHelpDialog(appShell, "helpDialog", args, n);
515 title = catgets(msgCatalog, 1, 4, "Template Help");
516 XtVaSetValues(XtParent(helpDialog), XmNtitle, title, NULL);
518 XtVaSetValues(helpDialog,
519 DtNhelpVolume, HelpVolume,
520 DtNlocationId, HelpTopic,
523 XtManageChild(helpDialog);
528 * Clear the display and drawing data.
531 static void ClearCb(Widget w, XtPointer cd, XtPointer cb)
533 WindowData *wd = (WindowData *)cd;
534 Widget drawingArea = XtNameToWidget(wd->shell, "*drawingArea");
537 XClearWindow(XtDisplay(drawingArea), XtWindow(drawingArea));
542 * Create a new top-level window.
544 static void NewCb(Widget w, XtPointer cd, XtPointer cb)
546 (void) NewWindow(LOAD_EMPTY, NULL, 0);
551 * Display a File dialog. On the first call, create the dialog.
554 static void OpenCb(Widget w, XtPointer cd, XtPointer cb)
556 WindowData *wd = (WindowData *)cd;
558 if (wd->openDialog == NULL) {
560 XmString dialogTitle;
564 dialogTitle = XmStringCreateLocalized(catgets(msgCatalog, 1, 2,
566 pattern = XmStringCreateLocalized(SearchPattern);
568 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL);n++;
569 XtSetArg(args[n], XmNautoUnmanage, True); n++;
570 XtSetArg(args[n], XmNpattern, pattern); n++;
571 XtSetArg(args[n], XmNdialogTitle, dialogTitle); n++;
572 wd->openDialog = XmCreateFileSelectionDialog(wd->shell, "openDialog",
574 XtUnmanageChild(XtNameToWidget(wd->openDialog, "*Help"));
575 XtAddCallback(wd->openDialog, XmNokCallback, OpenOkCb, cd);
576 XmStringFree(pattern);
577 XmStringFree(dialogTitle);
579 XtManageChild(wd->openDialog);
582 static void OpenOkCb(Widget w, XtPointer cd, XtPointer cb)
585 WindowData *wd = (WindowData *)cd;
586 XmFileSelectionBoxCallbackStruct *fsbcs =
587 (XmFileSelectionBoxCallbackStruct *) cb;
588 Widget drawingArea = XtNameToWidget(wd->shell, "*drawingArea");
590 fileName = XmStringUnparse(fsbcs->value, NULL, XmCHARSET_TEXT,
591 XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
592 (void) LoadFile(wd, fileName);
595 XClearArea(XtDisplay(drawingArea), XtWindow(drawingArea), 0, 0, 0, 0, True);
600 * Display a File dialog. On the first call, create the dialog.
603 static void SaveCb(Widget w, XtPointer cd, XtPointer cb)
605 WindowData *wd = (WindowData *)cd;
607 if (wd->saveDialog == NULL) {
609 XmString dialogTitle;
613 dialogTitle = XmStringCreateLocalized(catgets(msgCatalog, 1, 3,
614 "Template Save As"));
615 pattern = XmStringCreateLocalized(SearchPattern);
617 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL);n++;
618 XtSetArg(args[n], XmNautoUnmanage, True); n++;
619 XtSetArg(args[n], XmNpattern, pattern); n++;
620 XtSetArg(args[n], XmNdialogTitle, dialogTitle); n++;
621 wd->saveDialog = XmCreateFileSelectionDialog(appShell, "saveAsDialog",
623 XtUnmanageChild(XtNameToWidget(wd->saveDialog, "*Help"));
624 XtAddCallback(wd->saveDialog, XmNokCallback, SaveOkCb, cd);
625 XmStringFree(pattern);
626 XmStringFree(dialogTitle);
629 XtManageChild(wd->saveDialog);
632 static void SaveOkCb(Widget w, XtPointer cd, XtPointer cb)
638 WindowData *wd = (WindowData *)cd;
640 XmFileSelectionBoxCallbackStruct *fsbcs =
641 (XmFileSelectionBoxCallbackStruct *) cb;
642 XmStringGetLtoR(fsbcs->value, XmFONTLIST_DEFAULT_TAG, &fileName);
643 fileLength = strlen(fileName);
645 if (fileName[fileLength-1]== '/') {
646 fileName = AppendString(fileName, UnnamedFile);
647 fileLength = strlen(fileName);
650 if (fileLength > SuffixLength) {
651 if (strcmp(fileName+fileLength-SuffixLength, Suffix) != 0) {
652 fileName = AppendString(fileName,Suffix);
656 fileName = AppendString(fileName, Suffix);
659 if ((fp = fopen(fileName, "w")) != NULL) {
660 fputs(FileSignature, fp);
661 for (i=0; i < wd->npoints; i++)
662 fprintf(fp, "%d %d\n", wd->points[i].x, wd->points[i].y);
665 wd->name = XtNewString(fileName);
666 SetTitle(wd->shell, fileName);
672 static char* AppendString(char *base, char *suffix)
676 file = XtMalloc(strlen(base)+strlen(suffix)+1);
678 strcat(file, suffix);
685 * Respond to the TemplatePrint action by printing the data file
686 * specified to the '-print' option.
689 static void PrintCb(Widget w, XtPointer cd, XtPointer cb)
691 WindowData *wd = (WindowData *)cd;
697 * Redraw the display when exposed.
700 static void ExposeCb(Widget w, XtPointer cd, XtPointer cb)
702 XmDrawingAreaCallbackStruct *dcb = (XmDrawingAreaCallbackStruct*)cb;
706 if (dcb->event != NULL && dcb->event->xexpose.count > 0) return;
710 for (i = 0; i < wd->npoints; i++)
711 DrawPoint(w, wd->points[i].x, wd->points[i].y);
716 * Process mouse input.
719 static void InputCb(Widget w, XtPointer cd, XtPointer cb)
721 XmDrawingAreaCallbackStruct *dcb = (XmDrawingAreaCallbackStruct*)cb;
724 if (dcb->event->xany.type != ButtonPress &&
725 dcb->event->xany.type != MotionNotify)
730 AddPoint(wd, dcb->event->xbutton.x, dcb->event->xbutton.y);
731 DrawPoint(w, dcb->event->xbutton.x, dcb->event->xbutton.y);
736 * Delete the current window. If there are no more windows, exit the
740 static void ExitCb(Widget w, XtPointer cd, XtPointer cb)
742 WindowData *wd = (WindowData *)cd;
744 if (windowList == NULL)
750 * Handle WM_SAVE_YOURSELF by updating the command line with all the files
751 * currently being edited.
753 static void SaveSessionCb(Widget w, XtPointer cd, XtPointer cb)
756 int argcount = 1; /* starts at 1 for command name */
757 WindowData *wd = windowList;
761 /* count the number of windows bound to files */
762 for (wd = windowList; wd != NULL; wd = wd->next) {
763 if (wd->name != NULL)
767 command = (char **)XtMalloc(argcount*sizeof(char*));
770 for (wd = windowList; wd != NULL; wd = wd->next) {
771 if (wd->name != NULL)
772 command[i++] = wd->name;
775 first = windowList->shell;
776 XSetCommand(XtDisplay(first), XtWindow(first), command, i);
778 XChangeProperty(XtDisplay(w), XtWindow(w), XA_WM_COMMAND, XA_STRING, 8,
779 PropModeReplace, NULL, 0);
780 XtFree((char *)command);
785 * Accept .template files dropped on the drawing window.
788 static void DropTransferCb(Widget drawingArea, XtPointer cd, XtPointer cb)
790 DtDndTransferCallbackStruct *dcb = (DtDndTransferCallbackStruct*)cb;
791 WindowData *wd = FindData(drawingArea);
797 dcb->status = DtDND_FAILURE;
799 if (dcb->dropData->numItems > 1)
802 switch (dcb->dropData->protocol) {
804 case DtDND_FILENAME_TRANSFER:
805 fileName = dcb->dropData->data.files[0];
806 dataType = DtDtsFileToDataType(fileName);
807 if (strcmp(dataType, DataType) != 0) {
808 DtDtsFreeDataType(dataType);
811 if (LoadFile(wd, fileName))
812 dcb->status = DtDND_SUCCESS;
813 DtDtsFreeDataType(dataType);
816 case DtDND_BUFFER_TRANSFER:
817 bufPtr = dcb->dropData->data.buffers[0].bp;
818 bufLen = dcb->dropData->data.buffers[0].size;
819 dataType = DtDtsBufferToDataType(bufPtr, bufLen, NULL);
820 if (strcmp(dataType, DataType) != 0) {
821 DtDtsFreeDataType(dataType);
824 if (LoadBuffer(wd, bufPtr, bufLen))
825 dcb->status = DtDND_SUCCESS;
826 DtDtsFreeDataType(dataType);
830 XClearArea(XtDisplay(drawingArea), XtWindow(drawingArea),
836 * Set the widget's title to the program name followed by a separator followed
837 * by the trailing pathname component of the filename. The widget must be a
838 * shell. If name is NULL, uses "(untitled)" instead.
841 SetTitle(Widget w, char *name)
849 p = strrchr(name, '/');
855 sprintf(buf, "%s%s%s", appnameString, separatorString, p);
856 XtVaSetValues(w, XtNtitle, buf, NULL);
861 * Create a new WindowData structure. The widget passed in should be the
862 * shell associated with this data. It must be realized.
869 wd = XtNew(WindowData);
874 wd->openDialog = NULL;
875 wd->saveDialog = NULL;
878 /* push it onto the front of the global list */
879 wd->next = windowList;
887 * Associate a top-level shell with a WindowData structure. The shell must be
891 AssocData(WindowData *wd, Widget w)
894 XSaveContext(XtDisplay(w), XtWindow(w), wdContext, (XPointer)wd);
899 * Given a widget, find the WindowData structure associated with it. First it
900 * finds the shell ancestor of this widget, and then it extracts the window
901 * data from using the X Context Manager.
906 WindowData *wd = NULL;
908 while (! XtIsShell(w))
910 XFindContext(XtDisplay(w), XtWindow(w), wdContext, &wd);
916 * Destroy a WindowData structure.
919 DestroyData(WindowData *wd)
925 if (wd->shell != NULL)
926 XtDestroyWidget(wd->shell);
927 if (wd->openDialog != NULL)
928 XtDestroyWidget(wd->openDialog);
929 if (wd->saveDialog != NULL)
930 XtDestroyWidget(wd->saveDialog);
932 /* remove from the global list */
947 * Load a .template data file
950 static Boolean LoadFile(WindowData *wd, char *fileName)
956 if ((fp = fopen(fileName, "r")) == NULL)
959 if (fgets(sig, sizeof(sig), fp) == NULL) {
964 if (strcmp(sig, FileSignature) != 0) {
970 while (fscanf(fp, "%d %d", &x, &y) != EOF)
973 if (wd->shell != NULL)
974 SetTitle(wd->shell, fileName);
975 wd->name = XtNewString(fileName);
981 * Load a .template buffer
984 static Boolean LoadBuffer(WindowData *wd, void *buf, int len)
986 char *bufp = (char *)buf;
987 char *endp = bufp + len;
991 (void) strncpy(sig, bufp, sizeof(FileSignature) - 1);
992 sig[sizeof(FileSignature) - 1] = '\0';
993 if (strcmp(sig, FileSignature) != 0)
995 bufp += sizeof(FileSignature) - 1;
998 while (bufp < endp) {
999 if (sscanf(bufp, "%d %d\n%n", &x, &y, &l) != 2)
1004 if (wd->shell != NULL)
1005 SetTitle(wd->shell, NULL);
1015 Tt_status diagnosis,
1016 unsigned char *contents,
1021 int mark = tt_mark();
1022 char *opstr = tt_message_op(msg);
1024 if (strcmp(opstr, "Edit") == 0) {
1026 if (NewWindow(LOAD_FILE, file, 0))
1027 tt_message_reply(msg);
1029 tttk_message_fail(msg, TT_ERR_OP, "open failed", False);
1030 } else if (contents != NULL && len > 0) {
1031 if (NewWindow(LOAD_BUFFER, (char *)contents, len))
1032 tt_message_reply(msg);
1034 tttk_message_fail(msg, TT_ERR_OP, "load buffer failed", False);
1036 tttk_message_fail(msg, TT_ERR_OP, "no file or buffer", False);
1039 tttk_message_fail(msg, TT_ERR_OP, "unsupported message", False);
1043 tt_free((char *)contents);
1046 tt_message_destroy(msg);
1052 * Print the drawing data.
1054 * This function is intentionally left blank.
1057 static void PrintData(WindowData *wd)
1062 PS = popen("/usr/bin/lp", "w");
1065 fputs("clippath pathbbox 0 exch translate pop pop pop\n", PS);
1066 fputs("1 -1 scale 72 72 translate\n", PS);
1067 fputs("newpath 0.5 setgray\n", PS);
1068 fputs("/S { 10 0 360 arc fill } def\n", PS);
1070 for (i = 0; i < wd->npoints; i++)
1071 fprintf(PS, "%d %d S\n", wd->points[i].x, wd->points[i].y);
1073 fputs("showpage\n", PS);
1079 * Free drawing data structure
1082 static void FreeData(WindowData *wd)
1084 XtFree((char *)wd->points);
1090 if (wd->shell != NULL)
1091 SetTitle(wd->shell, NULL);
1096 * Add a point to the end of the drawing data structure.
1099 static void AddPoint(WindowData *wd, int x, int y)
1101 if (wd->npoints == wd->nalloc) {
1102 wd->nalloc += MallocInc;
1104 (XPoint*)XtRealloc((char*)wd->points, wd->nalloc * sizeof(XPoint));
1106 wd->points[wd->npoints].x = x;
1107 wd->points[wd->npoints].y = y;
1113 * Draw an airbrush at (x,y)
1116 static void DrawPoint(Widget w, int x, int y)
1118 static Boolean initialized = False;
1120 static Pixmap pixmap;
1121 static unsigned int pixmapWidth, pixmapHeight;
1123 if (XtIsRealized(w) == False) return;
1125 if (initialized == False) {
1133 XtVaGetValues(w, XmNforeground, &fg, XmNbackground, &bg, NULL);
1134 pixmap = XmGetPixmapByDepth(XtScreen(w), "template-brush.bm", 1, 0, 1);
1135 if (pixmap == XmUNSPECIFIED_PIXMAP) {
1136 XtAppWarning(appContext, "template:template-brush.bm not installed!");
1137 /* use hardcoded fallback bitmap */
1138 pixmap = XCreatePixmapFromBitmapData(XtDisplay(w), XtWindow(w),
1139 (char*)default_brush_bits,
1140 default_brush_width,
1141 default_brush_height,
1144 XGetGeometry(XtDisplay(w), pixmap, &tmpw, &tmpi, &tmpi,
1145 &pixmapWidth, &pixmapHeight, &tmpu, &tmpu);
1147 gcm = GCForeground | GCBackground | GCFillStyle | GCStipple;
1148 gcv.foreground = fg;
1149 gcv.background = bg;
1150 gcv.fill_style = FillStippled;
1151 gcv.stipple = pixmap;
1152 gc = XCreateGC(XtDisplay(w), XtWindow(w), gcm, &gcv);
1157 XSetTSOrigin(XtDisplay(w), gc, x-pixmapWidth/2, y-pixmapWidth/2);
1158 XFillRectangle(XtDisplay(w), XtWindow(w), gc,
1159 x-pixmapWidth/2, y-pixmapWidth/2,
1160 pixmapWidth, pixmapHeight);