/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $TOG: template.c /main/6 1999/09/20 15:48:19 mgreess $ */ /* * (c) Copyright 1993, 1994 Hewlett-Packard Company * (c) Copyright 1993, 1994 International Business Machines Corp. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * (c) Copyright 1993, 1994 Novell, Inc. */ /* * template.c * * Example code for typical Dt application * * Simple spray-can drawing tool */ #include #include #include
#include #include
#include
#include
#include /* default brush - used when the brush bitmap file is not found at run-time. */ #include "default_brush.bm" /* Portability for catopen */ #if !defined(NL_CAT_LOCALE) #define NL_CAT_LOCALE 0 #endif #define ApplicationClass "Template" #define MessageCatalog "template.cat" #define HelpVolume "template" #define HelpTopic "_hometopic" #define IconPixmap "template_icon.pm" #define IconMask "template_icon_m.bm" #define Suffix ".template" #define SuffixLength 9 #define UnnamedFile "unnamed.template" #define SearchPattern "*.template" #define DataType "TemplateData" #define ToolTalkPType "DT_Example_Template" #define FileSignature "@template@\n" #define MallocInc 10 typedef struct _WindowData { int npoints; int nalloc; XPoint *points; Widget shell; Widget openDialog; Widget saveDialog; char *name; /* NULL if no file */ struct _WindowData *next; } WindowData; static XtAppContext appContext; static nl_catd msgCatalog; static Widget appShell; static WindowData *windowList = NULL; static XContext wdContext; static Atom WM_DELETE_WINDOW; static Atom WM_SAVE_YOURSELF; static char *appnameString; static char *separatorString; static char *untitledString; static char *argv0; static char *programName; /* ToolTalk stuff */ static int ttfd; static char *procid; static Tt_pattern *ttpat; static Tt_status ttrc; static Tt_message HandleTtMedia(Tt_message, void *, Tttk_op, Tt_status, unsigned char *, int, char *, char *); #define DrawingTranslations "#replace\ : DrawingAreaInput()\n\ : DrawingAreaInput()" static void ClearCb(Widget, XtPointer, XtPointer); static void HelpCb(Widget, XtPointer, XtPointer); static void NewCb(Widget, XtPointer, XtPointer); static void OpenCb(Widget, XtPointer, XtPointer); static void OpenOkCb(Widget, XtPointer, XtPointer); static void SaveCb(Widget, XtPointer, XtPointer); static void SaveOkCb(Widget, XtPointer, XtPointer); static void PrintCb(Widget, XtPointer, XtPointer); static void ExitCb(Widget, XtPointer, XtPointer); static void ExposeCb(Widget, XtPointer, XtPointer); static void InputCb(Widget, XtPointer, XtPointer); static void DropTransferCb(Widget, XtPointer, XtPointer); static void SaveSessionCb(Widget, XtPointer, XtPointer); typedef enum { LOAD_EMPTY, LOAD_FILE, LOAD_BUFFER } LoadType; static void Fatal(char*); static void ReallyExit(int); static void SetTitle(Widget,char*); static Boolean NewWindow(LoadType,char*,int); static WindowData *NewData(void); static void AssocData(WindowData*,Widget); static WindowData *FindData(Widget); static void DestroyData(WindowData*); static Boolean LoadFile(WindowData*,char*); static Boolean LoadBuffer(WindowData*,void*,int); static void FreeData(WindowData*); static void PrintData(WindowData*); static void AddPoint(WindowData*, int, int); static void DrawPoint(Widget, int, int); static char* AppendString(char*,char*); static XtCallbackRec DropTransferCbList[] = { { DropTransferCb, NULL}, { NULL, NULL} }; static XrmOptionDescRec optionTable[] = { {"-print", ".printMode", XrmoptionIsArg, NULL}, {"-server", ".serverMode", XrmoptionIsArg, NULL}, }; typedef struct { String printMode; String serverMode; } appResourceRec; static XtResource appResources[] = { { "printMode", "PrintMode", XtRString, sizeof(String), XtOffsetOf(appResourceRec, printMode), XtRString, NULL }, { "serverMode", "ServerMode", XtRString, sizeof(String), XtOffsetOf(appResourceRec, serverMode), XtRString, NULL }, }; main(int argc, char **argv) { int i; appResourceRec argvals; char *errfmt, *errmsg, *statmsg; argv0 = argv[0]; programName = strrchr(argv[0], '/'); if (programName == NULL) programName = argv[0]; else ++programName; XtSetLanguageProc(NULL, NULL, NULL); appShell = XtAppInitialize(&appContext, ApplicationClass, optionTable, XtNumber(optionTable), &argc, argv, NULL, NULL, 0); msgCatalog = CATOPEN(MessageCatalog, NL_CAT_LOCALE); XtGetApplicationResources(appShell, &argvals, appResources, XtNumber(appResources), NULL, 0); wdContext = XUniqueContext(); WM_DELETE_WINDOW = XmInternAtom(XtDisplay(appShell), "WM_DELETE_WINDOW", False); WM_SAVE_YOURSELF = XmInternAtom(XtDisplay(appShell), "WM_SAVE_YOURSELF", False); appnameString = CATGETS(msgCatalog, 1, 1, "Template"); separatorString = CATGETS(msgCatalog, 1, 5, " - "); untitledString = CATGETS(msgCatalog, 1, 6, "(untitled)"); if (argvals.printMode != NULL) { /* Load up each file and print it, then exit */ WindowData *wd = NewData(); for (i = 1; i < argc; ++i) { if (LoadFile(wd, argv[i])) PrintData(wd); else fprintf(stderr, CATGETS(msgCatalog, 1, 10, "template: can't open %s\n"), argv[i]); } DestroyData(wd); exit(0); } /* Initialize Data Typing and ToolTalk */ DtDtsLoadDataTypes(); procid = ttdt_open(&ttfd, appnameString, "CDE", "1.0", True); if ((ttrc = tt_ptr_error(procid)) != TT_OK) { errfmt = CATGETS(msgCatalog, 1, 7, "ttdt_open failed:\n%s"); statmsg = tt_status_message(ttrc); errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2); sprintf(errmsg, errfmt, statmsg); Fatal(errmsg); XtFree(errmsg); } ttrc = ttmedia_ptype_declare(ToolTalkPType, 0, HandleTtMedia, NULL, True); if (tt_is_err(ttrc)) { errfmt = CATGETS(msgCatalog, 1, 8, "ttmedia_ptype_declare failed:\n%s"); statmsg = tt_status_message(status); errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2); sprintf(errmsg, errfmt, statmsg); Fatal(errmsg); XtFree(errmsg); } ttpat = ttdt_session_join(NULL, NULL, NULL, NULL, True); if ((ttrc = tt_ptr_error(ttpat)) != TT_OK) { errfmt = CATGETS(msgCatalog, 1, 9, "ttdt_session_join failed:\n%s"); statmsg = tt_status_message(status); errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2); sprintf(errmsg, errfmt, statmsg); Fatal(errmsg); XtFree(errmsg); } XtAppAddInput(appContext, ttfd, (XtPointer)XtInputReadMask, tttk_Xt_input_handler, NULL); if (argvals.serverMode != NULL) { /* * We're in server mode. Thus do nothing until requested to do so * through ToolTalk. */ } else if (argc < 2) { /* No files given, so put up an untitled window. */ (void) NewWindow(LOAD_EMPTY, NULL, 0); } else { /* Load each file into its own window. */ for (i = 1; i < argc; ++i) (void) NewWindow(LOAD_FILE, argv[i], 0); } /* * Start the GUI. Note that we explicitly do not realize the appShell * widget, since it is the unmapped parent of all of the top-level shells * we pop up. */ XtAppMainLoop(appContext); ReallyExit(0); } /* * Close ToolTalk and exit. */ static void ReallyExit(int rc) { tt_close(); exit(rc); } /* * Issue an error message and exit. */ static void Fatal(char *msg) { fprintf(stderr, "%s: %s\n", programName, msg); exit(1); } /* * Create a new top-level window. If loadtype is LOAD_EMPTY, name_or_buf and * len are ignored. If loadtype is LOAD_FILE, name_or_buf should point to the * name of the file to load, and len is ignored. If loadtype is LOAD_BUFFER, * name_or_buf is a pointer to the data buffer and len is its length. */ static Boolean NewWindow(LoadType loadtype, char *name_or_buf, int len) { Widget toplevel, mainWindow, menuBar, frame1, frame2, drawingArea, pd, cb, pb; char *title; XmString labelString; XtTranslations drawingTranslations; Pixmap iconPixmap; Pixmap iconMask; Pixel fg, bg; Arg args[20]; int n; WindowData *wd; wd = NewData(); n = 0; toplevel = XtCreatePopupShell("foo", topLevelShellWidgetClass, appShell, args, n); /* Create main window */ n = 0; mainWindow = XmCreateMainWindow(toplevel, "mainWindow", args, n); XtManageChild(mainWindow); /* Set window manager title and icon */ XtVaGetValues(mainWindow, XmNforeground, &fg, XmNbackground, &bg, NULL); iconPixmap = XmGetPixmap(XtScreen(toplevel), IconPixmap, fg, bg); iconMask = XmGetPixmapByDepth(XtScreen(toplevel), IconMask, 1, 0, 1); XtVaSetValues(toplevel, XmNiconName, appnameString, XmNiconPixmap, iconPixmap, XmNiconMask, iconMask, NULL); /* Create the GUI */ menuBar = XmCreateMenuBar(mainWindow, "menuBar", NULL, 0); XtManageChild(menuBar); /* File menu */ pd = XmCreatePulldownMenu(menuBar, "fileMenu", NULL, 0); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 1, "File")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'F'); n++; XtSetArg(args[n], XmNsubMenuId, pd); n++; cb = XmCreateCascadeButton(menuBar, "fileCascade", args, n); XtManageChild(cb); XmStringFree(labelString); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 9, "New...")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'N'); n++; pb = XmCreatePushButton(pd, "newButton", args, n); XtManageChild(pb); XtAddCallback(pb, XmNactivateCallback, NewCb, NULL); XmStringFree(labelString); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 2, "Open...")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'O'); n++; pb = XmCreatePushButton(pd, "openButton", args, n); XtManageChild(pb); XtAddCallback(pb, XmNactivateCallback, OpenCb, (XtPointer)wd); XmStringFree(labelString); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 3, "Save As...")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'S'); n++; pb = XmCreatePushButton(pd, "saveButton", args, n); XtManageChild(pb); XtAddCallback(pb, XmNactivateCallback, SaveCb, (XtPointer)wd); XmStringFree(labelString); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 4, "Print")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'P'); n++; pb = XmCreatePushButton(pd, "printButton", args, n); XtManageChild(pb); XtAddCallback(pb, XmNactivateCallback, PrintCb, (XtPointer)wd); XmStringFree(labelString); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 5, "Clear")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'C'); n++; pb = XmCreatePushButton(pd, "clearButton", args, n); XtManageChild(pb); XtAddCallback(pb, XmNactivateCallback, ClearCb, (XtPointer)wd); XmStringFree(labelString); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 6, "Exit")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'E'); n++; pb = XmCreatePushButton(pd, "exitButton", args, n); XtManageChild(pb); XtAddCallback(pb, XmNactivateCallback, ExitCb, (XtPointer)wd); XmStringFree(labelString); /* Help menu */ pd = XmCreatePulldownMenu(menuBar, "helpMenu", NULL, 0); labelString = XmStringCreateLocalized(CATGETS(msgCatalog, 2, 7, "Help")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'H'); n++; XtSetArg(args[n], XmNsubMenuId, pd); n++; cb = XmCreateCascadeButton(menuBar, "helpCascade", args, n); XtManageChild(cb); XmStringFree(labelString); XtVaSetValues(menuBar, XmNmenuHelpWidget, cb, NULL); labelString = XmStringCreateLocalized(CATGETS(msgCatalog,2,8, "Overview...")); n = 0; XtSetArg(args[n], XmNlabelString, labelString); n++; XtSetArg(args[n], XmNmnemonic, 'O'); n++; pb = XmCreatePushButton(pd, "helpButton", args, n); XtManageChild(pb); XtAddCallback(pb, XmNactivateCallback, HelpCb, NULL); XmStringFree(labelString); /* Drawing work area */ n = 0; XtSetArg(args[n], XmNshadowThickness, 0); n++; XtSetArg(args[n], XmNmarginWidth, 20); n++; XtSetArg(args[n], XmNmarginHeight, 20); n++; frame1 = XmCreateFrame(mainWindow, "frame1", args, n); XtManageChild(frame1); n = 0; XtSetArg(args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++; frame2 = XmCreateFrame(frame1, "frame2", args, n); XtManageChild(frame2); drawingTranslations = XtParseTranslationTable(DrawingTranslations); n = 0; XtSetArg(args[n], XmNunitType, Xm100TH_MILLIMETERS); n++; XtSetArg(args[n], XmNwidth, 12000); n++; XtSetArg(args[n], XmNheight, 12000); n++; XtSetArg(args[n], XmNtranslations, drawingTranslations); n++; drawingArea = XmCreateDrawingArea(frame2, "drawingArea", args, n); XtManageChild(drawingArea); XtAddCallback(drawingArea, XmNexposeCallback, ExposeCb, NULL); XtAddCallback(drawingArea, XmNinputCallback, InputCb, NULL); DtDndDropRegister(drawingArea, DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER, XmDROP_COPY, DropTransferCbList, NULL, 0); XmAddWMProtocolCallback(toplevel, WM_DELETE_WINDOW, ExitCb, (XtPointer)wd); XmAddWMProtocolCallback(toplevel, WM_SAVE_YOURSELF, SaveSessionCb, (XtPointer)NULL); XtRealizeWidget(toplevel); XtPopup(toplevel, XtGrabNone); AssocData(wd, toplevel); switch (loadtype) { case LOAD_EMPTY: SetTitle(toplevel, NULL); return True; case LOAD_FILE: return LoadFile(wd, name_or_buf); case LOAD_BUFFER: return LoadBuffer(wd, name_or_buf, len); } /*NOTREACHED*/ } /* * Display the help system. On the first call, create the help widget. */ static void HelpCb(Widget w, XtPointer cd, XtPointer cb) { static Widget helpDialog = NULL; if (helpDialog == NULL) { char *title; Arg args[10]; int n; n = 0; XtSetArg(args[n], DtNhelpVolume, HelpVolume); n++; XtSetArg(args[n], DtNhelpType, DtHELP_TYPE_TOPIC); n++; XtSetArg(args[n], DtNlocationId, HelpTopic); n++; helpDialog = DtCreateHelpDialog(appShell, "helpDialog", args, n); title = CATGETS(msgCatalog, 1, 4, "Template Help"); XtVaSetValues(XtParent(helpDialog), XmNtitle, title, NULL); } else { XtVaSetValues(helpDialog, DtNhelpVolume, HelpVolume, DtNlocationId, HelpTopic, NULL); } XtManageChild(helpDialog); } /* * Clear the display and drawing data. */ static void ClearCb(Widget w, XtPointer cd, XtPointer cb) { WindowData *wd = (WindowData *)cd; Widget drawingArea = XtNameToWidget(wd->shell, "*drawingArea"); FreeData(wd); XClearWindow(XtDisplay(drawingArea), XtWindow(drawingArea)); } /* * Create a new top-level window. */ static void NewCb(Widget w, XtPointer cd, XtPointer cb) { (void) NewWindow(LOAD_EMPTY, NULL, 0); } /* * Display a File dialog. On the first call, create the dialog. */ static void OpenCb(Widget w, XtPointer cd, XtPointer cb) { WindowData *wd = (WindowData *)cd; if (wd->openDialog == NULL) { XmString pattern; XmString dialogTitle; Arg args[20]; int n; dialogTitle = XmStringCreateLocalized(CATGETS(msgCatalog, 1, 2, "Template Open")); pattern = XmStringCreateLocalized(SearchPattern); n = 0; XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL);n++; XtSetArg(args[n], XmNautoUnmanage, True); n++; XtSetArg(args[n], XmNpattern, pattern); n++; XtSetArg(args[n], XmNdialogTitle, dialogTitle); n++; wd->openDialog = XmCreateFileSelectionDialog(wd->shell, "openDialog", args, n); XtUnmanageChild(XtNameToWidget(wd->openDialog, "*Help")); XtAddCallback(wd->openDialog, XmNokCallback, OpenOkCb, cd); XmStringFree(pattern); XmStringFree(dialogTitle); } XtManageChild(wd->openDialog); } static void OpenOkCb(Widget w, XtPointer cd, XtPointer cb) { char *fileName; WindowData *wd = (WindowData *)cd; XmFileSelectionBoxCallbackStruct *fsbcs = (XmFileSelectionBoxCallbackStruct *) cb; Widget drawingArea = XtNameToWidget(wd->shell, "*drawingArea"); fileName = XmStringUnparse(fsbcs->value, NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL); (void) LoadFile(wd, fileName); XtFree(fileName); XClearArea(XtDisplay(drawingArea), XtWindow(drawingArea), 0, 0, 0, 0, True); } /* * Display a File dialog. On the first call, create the dialog. */ static void SaveCb(Widget w, XtPointer cd, XtPointer cb) { WindowData *wd = (WindowData *)cd; if (wd->saveDialog == NULL) { XmString pattern; XmString dialogTitle; Arg args[20]; int n; dialogTitle = XmStringCreateLocalized(CATGETS(msgCatalog, 1, 3, "Template Save As")); pattern = XmStringCreateLocalized(SearchPattern); n = 0; XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL);n++; XtSetArg(args[n], XmNautoUnmanage, True); n++; XtSetArg(args[n], XmNpattern, pattern); n++; XtSetArg(args[n], XmNdialogTitle, dialogTitle); n++; wd->saveDialog = XmCreateFileSelectionDialog(appShell, "saveAsDialog", args, n); XtUnmanageChild(XtNameToWidget(wd->saveDialog, "*Help")); XtAddCallback(wd->saveDialog, XmNokCallback, SaveOkCb, cd); XmStringFree(pattern); XmStringFree(dialogTitle); } XtManageChild(wd->saveDialog); } static void SaveOkCb(Widget w, XtPointer cd, XtPointer cb) { FILE *fp; int i; char * fileName; int fileLength; WindowData *wd = (WindowData *)cd; XmFileSelectionBoxCallbackStruct *fsbcs = (XmFileSelectionBoxCallbackStruct *) cb; XmStringGetLtoR(fsbcs->value, XmFONTLIST_DEFAULT_TAG, &fileName); fileLength = strlen(fileName); if (fileName[fileLength-1]== '/') { fileName = AppendString(fileName, UnnamedFile); fileLength = strlen(fileName); } if (fileLength > SuffixLength) { if (strcmp(fileName+fileLength-SuffixLength, Suffix) != 0) { fileName = AppendString(fileName,Suffix); } } else { fileName = AppendString(fileName, Suffix); } if ((fp = fopen(fileName, "w")) != NULL) { fputs(FileSignature, fp); for (i=0; i < wd->npoints; i++) fprintf(fp, "%d %d\n", wd->points[i].x, wd->points[i].y); fclose(fp); XtFree(wd->name); wd->name = XtNewString(fileName); SetTitle(wd->shell, fileName); } XtFree(fileName); } static char* AppendString(char *base, char *suffix) { char *file; file = XtMalloc(strlen(base)+strlen(suffix)+1); strcpy(file, base); strcat(file, suffix); XtFree(base); return(file); } /* * Respond to the TemplatePrint action by printing the data file * specified to the '-print' option. */ static void PrintCb(Widget w, XtPointer cd, XtPointer cb) { WindowData *wd = (WindowData *)cd; PrintData(wd); } /* * Redraw the display when exposed. */ static void ExposeCb(Widget w, XtPointer cd, XtPointer cb) { XmDrawingAreaCallbackStruct *dcb = (XmDrawingAreaCallbackStruct*)cb; WindowData *wd; int i; if (dcb->event != NULL && dcb->event->xexpose.count > 0) return; wd = FindData(w); for (i = 0; i < wd->npoints; i++) DrawPoint(w, wd->points[i].x, wd->points[i].y); } /* * Process mouse input. */ static void InputCb(Widget w, XtPointer cd, XtPointer cb) { XmDrawingAreaCallbackStruct *dcb = (XmDrawingAreaCallbackStruct*)cb; WindowData *wd; if (dcb->event->xany.type != ButtonPress && dcb->event->xany.type != MotionNotify) return; wd = FindData(w); AddPoint(wd, dcb->event->xbutton.x, dcb->event->xbutton.y); DrawPoint(w, dcb->event->xbutton.x, dcb->event->xbutton.y); } /* * Delete the current window. If there are no more windows, exit the * application. */ static void ExitCb(Widget w, XtPointer cd, XtPointer cb) { WindowData *wd = (WindowData *)cd; DestroyData(wd); if (windowList == NULL) ReallyExit(0); } /* * Handle WM_SAVE_YOURSELF by updating the command line with all the files * currently being edited. */ static void SaveSessionCb(Widget w, XtPointer cd, XtPointer cb) { char **command; int argcount = 1; /* starts at 1 for command name */ WindowData *wd = windowList; int i; Widget first; /* count the number of windows bound to files */ for (wd = windowList; wd != NULL; wd = wd->next) { if (wd->name != NULL) ++argcount; } command = (char **)XtMalloc(argcount*sizeof(char*)); command[0] = argv0; i = 1; for (wd = windowList; wd != NULL; wd = wd->next) { if (wd->name != NULL) command[i++] = wd->name; } first = windowList->shell; XSetCommand(XtDisplay(first), XtWindow(first), command, i); if (w != first) XChangeProperty(XtDisplay(w), XtWindow(w), XA_WM_COMMAND, XA_STRING, 8, PropModeReplace, NULL, 0); XtFree((char *)command); } /* * Accept .template files dropped on the drawing window. */ static void DropTransferCb(Widget drawingArea, XtPointer cd, XtPointer cb) { DtDndTransferCallbackStruct *dcb = (DtDndTransferCallbackStruct*)cb; WindowData *wd = FindData(drawingArea); char *fileName; char *dataType; void *bufPtr; int bufLen; dcb->status = DtDND_FAILURE; if (dcb->dropData->numItems > 1) return; switch (dcb->dropData->protocol) { case DtDND_FILENAME_TRANSFER: fileName = dcb->dropData->data.files[0]; dataType = DtDtsFileToDataType(fileName); if (strcmp(dataType, DataType) != 0) { DtDtsFreeDataType(dataType); return; } if (LoadFile(wd, fileName)) dcb->status = DtDND_SUCCESS; DtDtsFreeDataType(dataType); break; case DtDND_BUFFER_TRANSFER: bufPtr = dcb->dropData->data.buffers[0].bp; bufLen = dcb->dropData->data.buffers[0].size; dataType = DtDtsBufferToDataType(bufPtr, bufLen, NULL); if (strcmp(dataType, DataType) != 0) { DtDtsFreeDataType(dataType); return; } if (LoadBuffer(wd, bufPtr, bufLen)) dcb->status = DtDND_SUCCESS; DtDtsFreeDataType(dataType); break; } XClearArea(XtDisplay(drawingArea), XtWindow(drawingArea), 0, 0, 0, 0, True); } /* * Set the widget's title to the program name followed by a separator followed * by the trailing pathname component of the filename. The widget must be a * shell. If name is NULL, uses "(untitled)" instead. */ static void SetTitle(Widget w, char *name) { char buf[1000]; char *p; if (name == NULL) { p = untitledString; } else { p = strrchr(name, '/'); if (p == NULL) p = name; else p++; } sprintf(buf, "%s%s%s", appnameString, separatorString, p); XtVaSetValues(w, XtNtitle, buf, NULL); } /* * Create a new WindowData structure. The widget passed in should be the * shell associated with this data. It must be realized. */ static WindowData * NewData(void) { WindowData *wd; wd = XtNew(WindowData); wd->npoints = 0; wd->nalloc = 0; wd->points = NULL; wd->shell = NULL; wd->openDialog = NULL; wd->saveDialog = NULL; wd->name = NULL; /* push it onto the front of the global list */ wd->next = windowList; windowList = wd; return wd; } /* * Associate a top-level shell with a WindowData structure. The shell must be * realized. */ static void AssocData(WindowData *wd, Widget w) { wd->shell = w; XSaveContext(XtDisplay(w), XtWindow(w), wdContext, (XPointer)wd); } /* * Given a widget, find the WindowData structure associated with it. First it * finds the shell ancestor of this widget, and then it extracts the window * data from using the X Context Manager. */ static WindowData * FindData(Widget w) { WindowData *wd = NULL; while (! XtIsShell(w)) w = XtParent(w); XFindContext(XtDisplay(w), XtWindow(w), wdContext, &wd); return wd; } /* * Destroy a WindowData structure. */ static void DestroyData(WindowData *wd) { WindowData **p; FreeData(wd); if (wd->shell != NULL) XtDestroyWidget(wd->shell); if (wd->openDialog != NULL) XtDestroyWidget(wd->openDialog); if (wd->saveDialog != NULL) XtDestroyWidget(wd->saveDialog); /* remove from the global list */ p = &windowList; while (*p != NULL) { if (*p == wd) { *p = wd->next; break; } p = &((*p)->next); } XtFree((char *)wd); } /* * Load a .template data file */ static Boolean LoadFile(WindowData *wd, char *fileName) { FILE *fp; int np, i, x, y; char sig[100]; if ((fp = fopen(fileName, "r")) == NULL) return False; if (fgets(sig, sizeof(sig), fp) == NULL) { fclose(fp); return False; } if (strcmp(sig, FileSignature) != 0) { fclose(fp); return False; } FreeData(wd); while (fscanf(fp, "%d %d", &x, &y) != EOF) AddPoint(wd, x, y); fclose(fp); if (wd->shell != NULL) SetTitle(wd->shell, fileName); wd->name = XtNewString(fileName); return True; } /* * Load a .template buffer */ static Boolean LoadBuffer(WindowData *wd, void *buf, int len) { char *bufp = (char *)buf; char *endp = bufp + len; int r, x, y, l; char sig[100]; (void) strncpy(sig, bufp, sizeof(FileSignature) - 1); sig[sizeof(FileSignature) - 1] = '\0'; if (strcmp(sig, FileSignature) != 0) return False; bufp += sizeof(FileSignature) - 1; FreeData(wd); while (bufp < endp) { if (sscanf(bufp, "%d %d\n%n", &x, &y, &l) != 2) return False; AddPoint(wd, x, y); bufp += l; } if (wd->shell != NULL) SetTitle(wd->shell, NULL); return True; } static Tt_message HandleTtMedia( Tt_message msg, void *clientdata, Tttk_op op, Tt_status diagnosis, unsigned char *contents, int len, char *file, char *docname) { int mark = tt_mark(); char *opstr = tt_message_op(msg); if (strcmp(opstr, "Edit") == 0) { if (file != NULL) { if (NewWindow(LOAD_FILE, file, 0)) tt_message_reply(msg); else tttk_message_fail(msg, TT_ERR_OP, "open failed", False); } else if (contents != NULL && len > 0) { if (NewWindow(LOAD_BUFFER, (char *)contents, len)) tt_message_reply(msg); else tttk_message_fail(msg, TT_ERR_OP, "load buffer failed", False); } else { tttk_message_fail(msg, TT_ERR_OP, "no file or buffer", False); } } else { tttk_message_fail(msg, TT_ERR_OP, "unsupported message", False); } tt_release(mark); tt_free((char *)contents); tt_free(file); tt_free(docname); tt_message_destroy(msg); return 0; } /* * Print the drawing data. * * This function is intentionally left blank. */ static void PrintData(WindowData *wd) { FILE *PS; int i; PS = popen("/usr/bin/lp", "w"); fputs("%!\n", PS); fputs("clippath pathbbox 0 exch translate pop pop pop\n", PS); fputs("1 -1 scale 72 72 translate\n", PS); fputs("newpath 0.5 setgray\n", PS); fputs("/S { 10 0 360 arc fill } def\n", PS); for (i = 0; i < wd->npoints; i++) fprintf(PS, "%d %d S\n", wd->points[i].x, wd->points[i].y); fputs("showpage\n", PS); (void) pclose(PS); } /* * Free drawing data structure */ static void FreeData(WindowData *wd) { XtFree((char *)wd->points); XtFree(wd->name); wd->points = NULL; wd->name = NULL; wd->npoints = 0; wd->nalloc = 0; if (wd->shell != NULL) SetTitle(wd->shell, NULL); } /* * Add a point to the end of the drawing data structure. */ static void AddPoint(WindowData *wd, int x, int y) { if (wd->npoints == wd->nalloc) { wd->nalloc += MallocInc; wd->points = (XPoint*)XtRealloc((char*)wd->points, wd->nalloc * sizeof(XPoint)); } wd->points[wd->npoints].x = x; wd->points[wd->npoints].y = y; wd->npoints += 1; } /* * Draw an airbrush at (x,y) */ static void DrawPoint(Widget w, int x, int y) { static Boolean initialized = False; static GC gc; static Pixmap pixmap; static unsigned int pixmapWidth, pixmapHeight; if (XtIsRealized(w) == False) return; if (initialized == False) { Pixel fg, bg; unsigned int tmpu; Window tmpw; int tmpi; XGCValues gcv; unsigned long gcm; XtVaGetValues(w, XmNforeground, &fg, XmNbackground, &bg, NULL); pixmap = XmGetPixmapByDepth(XtScreen(w), "template-brush.bm", 1, 0, 1); if (pixmap == XmUNSPECIFIED_PIXMAP) { XtAppWarning(appContext, "template:template-brush.bm not installed!"); /* use hardcoded fallback bitmap */ pixmap = XCreatePixmapFromBitmapData(XtDisplay(w), XtWindow(w), (char*)default_brush_bits, default_brush_width, default_brush_height, 1, 0, 1); } XGetGeometry(XtDisplay(w), pixmap, &tmpw, &tmpi, &tmpi, &pixmapWidth, &pixmapHeight, &tmpu, &tmpu); gcm = GCForeground | GCBackground | GCFillStyle | GCStipple; gcv.foreground = fg; gcv.background = bg; gcv.fill_style = FillStippled; gcv.stipple = pixmap; gc = XCreateGC(XtDisplay(w), XtWindow(w), gcm, &gcv); initialized = True; }; XSetTSOrigin(XtDisplay(w), gc, x-pixmapWidth/2, y-pixmapWidth/2); XFillRectangle(XtDisplay(w), XtWindow(w), gc, x-pixmapWidth/2, y-pixmapWidth/2, pixmapWidth, pixmapHeight); }