home *** CD-ROM | disk | FTP | other *** search
/ WordPerfect for Linux Bible / WP4LinuxBible.iso / sdk / wpx / code / wt / client / wtclfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-25  |  12.9 KB  |  435 lines

  1. /* SOURCE FILE *****************************************************
  2.  * WTCLFILE.C  -  WTAPI Sample Client Application file I/O functions
  3.  *******************************************************************
  4.  * Copyright (C) 1993 WordPerfect Corp., All Rights Reserved
  5.  *******************************************************************/
  6. #include "wtclient.h"
  7.  
  8. #include <Xm/Xm.h>
  9. #include <Xm/FileSB.h>
  10. #include <Xm/MessageB.h>
  11. #include <Xm/Text.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <fcntl.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17.  
  18. /*----------------------------------------------------------
  19.         External Variables
  20. ------------------------------------------------------------*/
  21. extern Widget Client;
  22. extern XmFontList FontList;
  23.  
  24. /*----------------------------------------------------------
  25.         External Functions
  26. ------------------------------------------------------------*/
  27. void SetNewBuffer(char *, char *);
  28. char *GetBuffer();
  29. XmString StringCreate(unsigned char *);
  30. void NormalCursor(Widget);
  31. void WaitCursor(Widget);
  32.  
  33. /*----------------------------------------------------------
  34.         Internal Variables
  35. ------------------------------------------------------------*/
  36. BOOL Dirty = FALSE;                    /* TRUE if the file is changed */
  37. char FileName[128] = "\0";            /* current file name */
  38. static Widget msgDialog, fileSelect;
  39. static BOOL MsgBoxRet = FALSE;
  40. static BOOL FileSelRet = FALSE;
  41. static char PathName[128] = "\0";            /* path to use for file selection */
  42. static char OpenDlgTitle[] = "Open File";    /* title of File open dialog */
  43. static char SaveDlgTitle[] = "Save File";    /* title of File saveas dialog */
  44. static char Untitled[] = "(untitled)";        /* default filename */
  45. static char *EditBuffer;                    /* editing buffer */
  46.  
  47. /*----------------------------------------------------------
  48.         Internal Functions
  49. ------------------------------------------------------------*/
  50. BOOL MsgBox(MSGBOX, Widget parent, char *, char *);
  51. static BOOL QuerySaveFile(Widget);
  52. static BOOL GetFileName(Widget, char *);
  53. static BOOL SaveFile(Widget);
  54.  
  55. /*COMMENT***************************************************
  56. ;FileMenuProc
  57. Title:    Handle File menu actions
  58. In:        parent - widget to be used as parent for subdialogs
  59.         file - File action to be performed
  60. Out:    none
  61. Xin:    Untitled, OpenDlgTitle, SaveDlgTitle
  62. Xout:    Dirty, FileName, EditBuffer
  63. Return:    NULL
  64. Notes:
  65. ***********************************************************/
  66. void FileMenuProc(Widget parent, CL_FILE file)
  67. {
  68.     char str[256];
  69.     struct stat statbuf;
  70.     int fd;
  71.  
  72.     switch (file) {
  73.         case CL_FILE_NEW:        /* New */
  74.             if (!QuerySaveFile(parent)) {    /* get rid of the old one? */
  75.                 return;                        /* no */
  76.             }
  77.             Dirty = FALSE;                    /* edit buffer is clean */
  78.             FileName[0] = 0;                /* no file name */
  79.             str[0] = 0;
  80.             SetNewBuffer(str, Untitled);    /* clear out buffer */
  81.             break;
  82.         case CL_FILE_OPEN:        /* Open */
  83.             /*
  84.              * Ask to save current buffer if changed.
  85.              */
  86.             if (!QuerySaveFile(parent)) {
  87.                 return;
  88.             }
  89.             /*
  90.              * Get the name of the file to open.  Use stat() to make sure
  91.              * it is accessible and to determine its size.
  92.              */
  93.             if (!GetFileName(parent, OpenDlgTitle)) {
  94.                 return;
  95.             }
  96.             if (stat(FileName, &statbuf) < 0) {
  97.                 sprintf(str, "Unable to stat: %s.", FileName);
  98.                 MsgBox(MB_OK, parent, "WTClient", str);
  99.                 return;
  100.             }
  101.             /*
  102.              * Allocate space to read in the file.
  103.              */
  104.             EditBuffer = (char *)calloc(1, statbuf.st_size + 1);
  105.             if (!EditBuffer) {
  106.                 MsgBox(MB_OK, parent, "WTClient", "Not enough memory.");
  107.                 return;
  108.             }
  109.             /*
  110.              * Open file and read contents into EditBuffer.
  111.              */
  112.             fd = open(FileName, O_RDONLY, 0);
  113.             if (fd < 0) {
  114.                 sprintf(str, "Unable to open: %s.", FileName);
  115.                 MsgBox(MB_OK, parent, "WTClient", str);
  116.                 return;
  117.             }
  118.             if (read(fd, EditBuffer, statbuf.st_size) != statbuf.st_size) {
  119.                 sprintf(str, "Error reading: %s.", FileName);
  120.                 MsgBox(MB_OK, parent, "WTClient", str);
  121.             }
  122.             close(fd);
  123.             /*
  124.              * Set up a new buffer and window title.
  125.              */
  126.             SetNewBuffer(EditBuffer, FileName);
  127.             free(EditBuffer);
  128.             break;
  129.         case CL_FILE_SAVE:        /* Save */
  130.             if (FileName[0]){                /* is there a filename? */
  131.                 if (Dirty) {                /* does it need saving? */
  132.                     SaveFile(parent);        /* then save it */
  133.                 }
  134.                 break;
  135.             }
  136.             /* else fall through, use SaveAs to get filename */
  137.         case CL_FILE_SAVE_AS:    /* Save As */
  138.             if (!GetFileName(parent, SaveDlgTitle)) {
  139.                 return;            /* User canceled */
  140.             }
  141.             /* If successful, update the window title, save the file */
  142.             sprintf(str, "WTClient - %s", FileName);
  143.             XtVaSetValues(Client, XtNtitle, str, NULL);
  144.             SaveFile(parent);
  145.             break;
  146.         case CL_FILE_PRINT:        /* Print */
  147.             MsgBox(MB_OK, parent, "WTClient - Print","Command not implemented");
  148.             break;
  149.         case CL_FILE_EXIT:        /* Exit */
  150.             QuerySaveFile(parent);
  151.             while (    !XtIsTopLevelShell(parent) &&
  152.                     !XtIsApplicationShell(parent) &&
  153.                     XtParent(parent) )
  154.             {
  155.                 parent = XtParent(parent);
  156.             }
  157.             XtDestroyWidget(parent);
  158.             break;
  159.         default:                /* unrecognized action */
  160.             break;                /* do nothing */
  161.     }
  162. } /* FileMenuProc */
  163.  
  164. /*COMMENT***************************************************
  165. ;SaveFile
  166. Title:    Save current file
  167. In:        parent - widget to be used as parent for subdialogs
  168. Out:    none
  169. Xin:    none
  170. Xout:    none
  171. Return:    none
  172. Notes:    This saves the current contents of the Edit buffer, and changes
  173.         Dirty to indicate that the buffer has not been changed since the
  174.         last save.
  175. ***********************************************************/
  176. static BOOL SaveFile(Widget parent)
  177. {
  178.     BOOL success;
  179.     char str[256];
  180.     int fd;
  181.     int len;
  182.  
  183.     WaitCursor(parent);
  184.     /*
  185.      * Open file for write.  Create it if it doesn't exist  and truncate it
  186.      * if it does.
  187.      */
  188.     fd = open(FileName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  189.     if (fd < 0) {
  190.         sprintf(str, "Cannot write: %s", FileName);
  191.         MsgBox(MB_OK, parent, "WTClient", str);
  192.         NormalCursor(parent);
  193.         return FALSE;
  194.     }
  195.     /*
  196.      * Write text to file.
  197.      */
  198.     EditBuffer = GetBuffer();
  199.     len = strlen(EditBuffer);
  200.     if (write(fd, EditBuffer, len) != len) {
  201.         sprintf(str, "Error writing: %s", FileName);
  202.         NormalCursor(parent);
  203.         MsgBox(MB_OK, parent, "WTClient", str);
  204.         success = FALSE;
  205.     } else {
  206.         success = TRUE;        /* Indicates the file was saved */
  207.         Dirty = FALSE;        /* Indicates changes have been saved */
  208.     }
  209.     XtFree(EditBuffer);    /* GetBuffer() uses XmTextGetString(), we must free */
  210.     close(fd);
  211.     NormalCursor(parent);
  212.     return (success);
  213. } /* SaveFile */
  214.  
  215. /*COMMENT***************************************************
  216. ;QuerySaveFile
  217. Title:    Called when some action might lose current contents of the edit buffer.
  218. In:        parent - widget to be used as parent for subdialogs
  219. Out:    none
  220. Xin:    none
  221. Xout:    none
  222. Return:    TRUE - file saved (if desired), FALSE - file not saved
  223. Notes:
  224. ***********************************************************/
  225. static BOOL QuerySaveFile(Widget parent)
  226. {
  227.     BOOL response;
  228.     char str[256];
  229.  
  230.     if (Dirty) {
  231.         if (!FileName[0]) {
  232.             sprintf(str, "Save current changes: %s", Untitled);
  233.         } else {
  234.             sprintf(str, "Save current changes: %s", FileName);
  235.         }
  236.         response = MsgBox(MB_YESNO, parent, "WTClient", str);
  237.         if (response == TRUE) {
  238.             /* Make sure there is a filename to save to */
  239.             while (!FileName[0]) {
  240.                 if (!GetFileName(parent, SaveDlgTitle)) {
  241.                     return FALSE;        /* User canceled */
  242.                 }
  243.             }
  244.             SaveFile(parent);
  245.         } else {
  246.             return TRUE;    /* user does not want buffer saved */
  247.         }
  248.     }
  249.     return TRUE;
  250. } /* QuerySaveFile */
  251.  
  252. /*COMMENT***************************************************
  253. ;MsgBoxCB
  254. Title:     MsgBox dialog callback
  255. In:        cladata - 1 = Yes, 0 = No
  256. Out:    none
  257. Return:    none
  258. Xin:    none
  259. Xout:    none
  260. Notes:
  261. ***********************************************************/
  262. static void MsgBoxCB(Widget w, XtPointer cldata, XtPointer cbdata)
  263. {
  264.     MsgBoxRet = ((int)cldata == 1);
  265.     if (msgDialog) {
  266.         XtDestroyWidget(msgDialog);
  267.     }
  268.     msgDialog = 0;
  269. } /* MsgBoxCB */
  270.  
  271. /*COMMENT***************************************************
  272. ;MsgBox
  273. Title:    Bring up an OK or Yes/No message dialog.
  274. In:        type - type of message box
  275.         parent - parent widget
  276.         title - dialog title
  277.         message - message/question for dialog
  278. Out:    none
  279. Xin:    none
  280. Xout:    none
  281. Return:    TRUE - Yes, FALSE - No
  282. Notes:
  283. ***********************************************************/
  284. BOOL MsgBox(MSGBOX type, Widget parent, char *title, char *message)
  285. {
  286.     Arg args[14];            /* Args for XtSetArg() */
  287.     Cardinal argcnt = 0;    /* number of Args set */
  288.     XmString titleStr, messageStr, yesStr, noStr;
  289.     XEvent event;
  290.  
  291.     MsgBoxRet = False;
  292.     titleStr = StringCreate(title);
  293.     messageStr = StringCreate(message);
  294.     if (type == MB_YESNO) {
  295.         yesStr = StringCreate("Yes");
  296.         noStr = StringCreate("No");
  297.     } else {
  298.         yesStr = StringCreate("OK");
  299.     }
  300.     argcnt = 0;
  301.     XtSetArg(args[argcnt], XmNdialogTitle, titleStr);  argcnt++;
  302.     XtSetArg(args[argcnt], XmNmessageString, messageStr);  argcnt++;
  303.     XtSetArg(args[argcnt], XmNokLabelString, yesStr);  argcnt++;
  304.     XtSetArg(args[argcnt], XmNtextFontList, FontList);  argcnt++;
  305.     XtSetArg(args[argcnt], XmNbuttonFontList, FontList);  argcnt++;
  306.     XtSetArg(args[argcnt], XmNlabelFontList, FontList);  argcnt++;
  307.     XtSetArg(args[argcnt], XmNdialogStyle,
  308.                             XmDIALOG_PRIMARY_APPLICATION_MODAL);  argcnt++;
  309.     XtSetArg(args[argcnt], XmNmessageAlignment, XmALIGNMENT_CENTER);  argcnt++;
  310.     if (type == MB_YESNO) {
  311.         XtSetArg(args[argcnt], XmNcancelLabelString, noStr);  argcnt++;
  312.         msgDialog = XmCreateQuestionDialog(parent, "quesDialog", args, argcnt);
  313.     } else {
  314.         msgDialog = XmCreateInformationDialog(parent, "infoDialog", args, argcnt);
  315.     }
  316.     XmStringFree(titleStr);
  317.     XmStringFree(messageStr);
  318.     XmStringFree(yesStr);
  319.     if (type == MB_YESNO) {
  320.         XmStringFree(noStr);
  321.         XtAddCallback(msgDialog, XmNcancelCallback, MsgBoxCB, 0);
  322.     } else {
  323.         XtUnmanageChild(XmMessageBoxGetChild(msgDialog,XmDIALOG_CANCEL_BUTTON));
  324.     }
  325.     XtAddCallback(msgDialog, XmNokCallback, MsgBoxCB, (XtPointer) 1);
  326.     XtUnmanageChild(XmMessageBoxGetChild(msgDialog, XmDIALOG_HELP_BUTTON));
  327.     XtManageChild(msgDialog);
  328.     /*
  329.      * Process events until dialog is closed.
  330.      */
  331.     for (;;) {
  332.         XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
  333.         XtDispatchEvent(&event);
  334.         if (!msgDialog) {
  335.             break;
  336.         }
  337.     }
  338.     return(MsgBoxRet);
  339. } /* MsgBox */
  340.  
  341. /*COMMENT***************************************************
  342. ;FileSelectCB
  343. Title:    Initialize the newly selected file.
  344. In:        w - file selection box
  345.         cldata - 1 = OK, 0 = Cancel
  346. Out:    none
  347. Xin:    none
  348. Xout:    FileName, PathName, FileSelRet
  349. Return:    none
  350. ***********************************************************/
  351. static void FileSelectCB(Widget w, XtPointer cldata, XtPointer cbdata)
  352. {
  353.     Widget text;    /* text child of FileSelectionBox */
  354.     String path;    /* pointer to path from text widget */
  355.     char *p;
  356.  
  357.     FileSelRet = ((int)cldata == 1);
  358.     if (FileSelRet) {        /* OK */
  359.         text = XmFileSelectionBoxGetChild(w, XmDIALOG_TEXT);
  360.         path = XmTextGetString(text);    /* Get user's specified path */
  361.         if (!path || !*path || strcmp(path, "/") == 0) {
  362.             return;        /* leave dialog up to get valid file name */
  363.         }
  364.         strcpy(FileName, path);
  365.         if (p = strrchr(path, '/')) {    /* find last slash */
  366.             *p = 0;                        /* truncate at last slash */
  367.         }
  368.         strcpy(PathName, path);
  369.         XtFree(path);
  370.     }
  371.     XtDestroyWidget(fileSelect);    /* Destroy file select dialog */
  372.     fileSelect = 0;
  373. } /* FileSelectCB */
  374.  
  375. /*COMMENT***************************************************
  376. ;GetFileName
  377. Title:    Use file selection dialog to get path to desired file
  378. In:        parent - widget to be used as parent for file selection dialog
  379.         title - title for file selection dialog
  380. Out:    none
  381. Xin:    PathName
  382. Xout:    FileSelRet
  383. Return:    none
  384. Notes:
  385. ***********************************************************/
  386. static BOOL GetFileName(Widget parent, char *title)
  387. {
  388.     Arg args[8];            /* Args for XtSetArg() */
  389.     Cardinal argcnt = 0;    /* number of Args set */
  390.     XmString dirStr;        /* for XmNdirectory */
  391.     XmString dirmaskStr;    /* for XmNdirMask */
  392.     XmString titleStr;        /* for XmNdialogTitle */
  393.     XEvent event;
  394.  
  395.     FileSelRet = FALSE;
  396.     argcnt = 0;
  397.     /*
  398.      * If the PathName is not empty use it for XmNdirectory, otherwise
  399.      * default to the current directory.
  400.      */
  401.     if (*PathName) {
  402.         dirStr = StringCreate(PathName);
  403.         XtSetArg(args[argcnt], XmNdirectory, dirStr);  argcnt++;
  404.     } else {
  405.         dirStr = 0;
  406.     }
  407.     dirmaskStr = StringCreate("*");
  408.     titleStr = StringCreate(title);
  409.     XtSetArg(args[argcnt], XmNdirMask, dirmaskStr);  argcnt++;
  410.     XtSetArg(args[argcnt], XmNdialogTitle, titleStr);  argcnt++;
  411.     XtSetArg(args[argcnt], XmNtextFontList, FontList);  argcnt++;
  412.     XtSetArg(args[argcnt], XmNbuttonFontList, FontList);  argcnt++;
  413.     XtSetArg(args[argcnt], XmNlabelFontList, FontList);  argcnt++;
  414.     fileSelect = XmCreateFileSelectionDialog(parent, "filesel", args, argcnt);
  415.     if (dirStr) {
  416.         XmStringFree(dirStr);
  417.     }
  418.     XmStringFree(dirmaskStr);
  419.     XmStringFree(titleStr);
  420.     XtAddCallback(fileSelect, XmNokCallback, FileSelectCB, (XtPointer)1);
  421.     XtAddCallback(fileSelect, XmNcancelCallback, FileSelectCB, 0);
  422.     XtManageChild(fileSelect);
  423.     /*
  424.      * Process events until dialog is closed.
  425.      */
  426.     for (;;) {
  427.         XtAppNextEvent(XtWidgetToApplicationContext(parent), &event);
  428.         XtDispatchEvent(&event);
  429.         if (!fileSelect) {
  430.             break;
  431.         }
  432.     }
  433.     return(FileSelRet);
  434. } /* GetFileName */
  435.