home *** CD-ROM | disk | FTP | other *** search
- /*
- * main.c
- *
- * notes - by Bob Smith <bob@snuffy.dracut.ma.us>
- */
-
- #include <stdio.h>
- #include <strings.h>
- #include <malloc.h>
- #include <sys/param.h> /* for MAXPATHLEN */
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Shell.h>
-
- #include <X11/Xaw/Box.h>
- #include <X11/Xaw/Cardinals.h>
- #include <X11/Xaw/Command.h>
- #include <X11/Xaw/Label.h>
- #include <X11/Xaw/Form.h>
- #include <X11/Xaw/List.h>
-
- #include "notes.h"
-
-
- /*
- * Global Variables
- */
- XtAppContext app_con;
- Widget toplevel;
- Widget start_button;
-
- Widget **Notes;
- char **Titles;
-
- char notefile[MAXPATHLEN];
-
-
- /*
- * forward declarations
- */
- void die(), write_notefile(), sensitize_start_button();
- static void dismiss_all(), dismiss_note(), save_dismiss_all();
- static void version(), ask_quit(), desensitize_start_button();
-
-
- /*
- * external functions
- */
- /* in callbacks.c */
- extern void null(), show_list(), quit(), destroy_widget(), destroy_list();
- extern Widget *make_note_widget();
-
-
- /*
- * XtActionsRec actionTable
- */
- static XtActionsRec actionTable[] = {
- { "null", null },
- { "quit", quit },
- { "ask_quit", ask_quit },
- { "version", version },
- { "dismiss_all", dismiss_all },
- { "dismiss_note", dismiss_note },
- { "save_dismiss_all", save_dismiss_all },
- };
-
-
- /*
- * fallback_resources
- */
- static char *fallback_resources[] = {
- "notes.start_button.bitmap: notes.xbm",
- "*List.Columns: 1",
- "*input*translations: #override \\n\
- <Key>Return: null() \\n\
- <Key>Tab: null() \\n\
- Ctrl<Key>J: null()",
- "*start_button*translations: #override \\n\
- <Key>q: quit() \\n\
- <Key>Q: quit() \\n\
- <Key>v: version() \\n\
- <Key>V: version() \\n\
- <Btn2Down>: set() \\n\
- <Btn2Down>,<Btn2Up>: version() reset() \\n\
- <Btn3Down>: set() \\n\
- <Btn3Down>,<Btn3Up>: ask_quit() reset()",
- "*Notes*dismiss_button*translations: #override \\n\
- <Btn2Down>: set() \\n\
- <Btn2Down>,<Btn2Up>: dismiss_all() reset()",
- "*Notes*save_button*translations: #override \\n\
- <Btn2Down>: set() \\n\
- <Btn2Down>,<Btn2Up>: save_dismiss_all() reset()",
- "*Notes*list*translations: #override \\n\
- <Btn2Down>: Set() \\n\
- <Btn2Down>,<Btn2Up>: dismiss_note() Unset()",
- NULL
- };
-
-
- #ifdef NEED_STRDUP
- /*
- * strdup ()
- */
- char *
- strdup(s)
- char *s;
- {
- char *t;
-
- if ((t = malloc(strlen(s)+1)) == NULL)
- die("Malloc in strdup failed.");
- strcpy(t, s);
- return t;
- }
- #endif
-
-
- /*
- * die ()
- */
- void
- die(s)
- char *s;
- {
- fprintf(stderr, "%s\n", s);
- fflush(stderr);
- quit();
- }
-
-
- /*
- * dismiss_all ()
- * dismiss all notes and the list widget
- */
- static void
- dismiss_all(widget, client_data, call_data)
- Widget widget;
- XtPointer client_data, call_data;
- {
- int i;
- XWindowAttributes atribs;
-
- i = 0;
- while (Notes[i]) {
- XGetWindowAttributes(XtDisplay(*Notes[i]),
- XtWindow(*Notes[i]), &atribs);
- if (atribs.map_state != IsUnmapped) {
- XtPopdown(*Notes[i]);
- XtUnmapWidget(*Notes[i]);
- }
- i++;
- }
- destroy_list();
- sensitize_start_button();
- }
-
-
- /*
- * save_dismiss_all ()
- * save the notefile and dismiss all notes and the list
- */
- static void
- save_dismiss_all(widget, client_data, call_data)
- Widget widget;
- XtPointer client_data, call_data;
- {
- write_notefile();
- dismiss_all();
- }
-
-
- /*
- * dismiss_note ()
- * dismiss a note
- */
- static void
- dismiss_note(widget, client_data, call_data)
- Widget widget;
- XtPointer client_data, call_data;
- {
- XawListReturnStruct *item;
- Widget w;
- XWindowAttributes atribs;
-
- item = XawListShowCurrent(widget);
- if (item->list_index == -1)
- return;
-
- w = *Notes[item->list_index];
- XGetWindowAttributes(XtDisplay(w), XtWindow(w), &atribs);
-
- if (atribs.map_state != IsUnmapped) {
- XtPopdown(w);
- XtUnmapWidget(w);
- }
- }
-
-
- /*
- * ask_quit()
- */
- static void
- ask_quit(widget, client_data, call_data)
- Widget widget;
- XtPointer client_data, call_data;
- {
- Widget popup, form, prompt;
- Widget confirm_button, filler_box, cancel_button;
- Dimension top_w, pop_w;
- Position x, y;
-
- desensitize_start_button();
-
- popup = XtCreatePopupShell("Quit",
- transientShellWidgetClass, toplevel,
- NULL, ZERO);
-
- form = XtCreateManagedWidget("form",
- formWidgetClass, popup,
- NULL, ZERO);
-
- prompt = XtVaCreateManagedWidget("prompt",
- labelWidgetClass, form,
- XtNlabel, "Quit, Are you sure?",
- XtNborderWidth, 0,
- XtNtop, XawChainTop,
- XtNbottom, XawChainTop,
- XtNleft, XawChainLeft,
- XtNright, XawChainLeft,
- NULL);
-
- confirm_button = XtVaCreateManagedWidget("confirm_button",
- commandWidgetClass, form,
- XtNlabel, "Yes",
- XtNwidth, 64,
- XtNfromVert, prompt,
- XtNtop, XawChainBottom,
- XtNbottom, XawChainBottom,
- XtNleft, XawChainLeft,
- XtNright, XawChainLeft,
- NULL);
- AddCallback(confirm_button, quit, NULL);
-
- filler_box = XtVaCreateManagedWidget("filler_box",
- boxWidgetClass, form,
- XtNwidth, 64,
- XtNborderWidth, 0,
- XtNfromHoriz, confirm_button,
- XtNfromVert, prompt,
- XtNtop, XawChainBottom,
- XtNbottom, XawChainBottom,
- XtNleft, XawChainLeft,
- XtNright, XawChainRight,
- NULL);
-
- cancel_button = XtVaCreateManagedWidget("cancel_button",
- commandWidgetClass, form,
- XtNlabel, "No",
- XtNwidth, 64,
- XtNfromHoriz, filler_box,
- XtNfromVert, prompt,
- XtNtop, XawChainBottom,
- XtNbottom, XawChainBottom,
- XtNleft, XawChainRight,
- XtNright, XawChainRight,
- NULL);
- AddCallback(cancel_button, destroy_widget, NULL);
- AddCallback(cancel_button, sensitize_start_button, NULL);
-
- XtRealizeWidget(popup);
-
- XtVaGetValues(toplevel, XtNwidth, &top_w, NULL);
- XtVaGetValues(popup, XtNwidth, &pop_w, NULL);
- XtTranslateCoords(toplevel, (top_w-pop_w)/2, 0, &x, &y);
- XtVaSetValues(popup, XtNx, x, XtNy, y, NULL);
-
- XtPopup(popup, XtGrabNone);
- }
-
- /*
- * sort_titles ()
- * sort the titles and return the new index of where widget
- * `j' ended up
- */
- int
- sort_titles(j)
- int j;
- {
- int i;
- char *s;
-
- i = 0;
- while (Titles[i] && Titles[i+1]) {
- if (strcmp(Titles[i], Titles[i+1]) > 0) {
- if (j == i)
- j++;
- else
- if (j == i+1)
- j--;
- s = Titles[i];
- Titles[i] = Titles[i+1];
- Titles[i+1] = s;
- s = (char *) Notes[i];
- Notes[i] = Notes[i+1];
- Notes[i+1] = (Widget *) s;
- i = 0;
- } else
- i++;
- }
- return j;
- }
-
-
- /*
- * read_notefile ()
- * read the notefile and make a note widget for each note
- */
- void
- read_notefile()
- {
- FILE *fp;
- char title[80];
- char *buffer, *s, *t;
- int i, x, y, w, h;
- char *getenv();
- struct stat sbuf;
-
- Notes = (Widget **) malloc(sizeof(char *));
- Titles = (char **) malloc(sizeof(char *));
- if (!Notes || !Titles)
- die("Malloc in read_notefile failed.");
- *Notes = NULL;
- *Titles = NULL;
-
- /*
- * check the current directory, and then the HOME
- * directory... if there is no .notes file, free the
- * temp buffer and get out of here leaving notefile
- * pointing to the HOME directory
- */
- strcpy(notefile, NOTEFILE);
- if ((fp = fopen(notefile, "r")) == NULL) {
- if ((s = getenv("HOME")) == NULL)
- return;
- strcpy(notefile, s);
- strcat(notefile, "/");
- strcat(notefile, NOTEFILE);
- if ((fp = fopen(notefile, "r")) == NULL)
- return;
- }
-
- /*
- * check the size of the notes file and allocate a buffer
- * of appropriate size
- */
- if (fstat(fileno(fp), &sbuf) == 0) {
- if ((buffer = malloc(sbuf.st_size+1)) == NULL) {
- fclose(fp);
- die("Malloc of buffer in read_notefile failed.");
- }
- } else {
- fclose(fp);
- die("Can't stat notes file.");
- }
-
- /*
- * read the notes file into the temp buffer
- */
- if ((i = fread(buffer, sbuf.st_size, 1, fp)) != 1) {
- fclose(fp);
- die("Read error on notes file.");
- }
- buffer[sbuf.st_size] = '\0';
- fclose(fp);
-
- /*
- * spin through the temp buffer and setup the initial
- * state of the NoteStruct pointers...
- */
- s = buffer;
- i = 0;
- while (*s) {
- if (*s == '\f') {
- *s = '\0';
- speed_hack:;
- i++;
- Notes = (Widget **) realloc(Notes, (i+1)*sizeof(char *));
- Titles = (char **) realloc(Titles, (i+1)*sizeof(char *));
- if (!Notes || !Titles)
- die("Realloc in read_notefile failed.");
- s++;
- if ((t = index(s, '\n')) == NULL)
- die("Oop! No newline at end of title?");
- else {
- sscanf(s, "%d %d %d %d %[^\n]", &x, &y, &w, &h, title);
- s = ++t;
- if ((t = index(s, '\f')) != NULL) *t = '\0';
- Notes[i-1] = make_note_widget(title, x, y, w, h, s);
- Notes[i] = NULL;
- Titles[i-1] = strdup(title);
- Titles[i] = NULL;
- if (t) {
- s = t;
- /* this is ugly, but it works... */
- goto speed_hack;
- }
- }
- } else
- s++;
- }
- free(buffer);
- (void) sort_titles(0);
- }
-
-
- /*
- * alloc_new_note ()
- * make a new note
- */
- int
- alloc_new_note(title)
- char *title;
- {
- int i;
- Position top_w, x, y;
-
- XtVaGetValues(toplevel, XtNwidth, &top_w, NULL);
- XtTranslateCoords(toplevel, (top_w - 512)/2, 0, &x, &y);
-
- i = 0;
- while (Notes[i]) i++;
- i++;
- Notes = (Widget **) realloc(Notes, (i+1)*sizeof(char *));
- Titles = (char **) realloc(Titles, (i+1)*sizeof(char *));
- if (!Notes || !Titles)
- die("Realloc in alloc_new_note failed.");
- Notes[i-1] = make_note_widget(title, x, y, 500, 300, "");
- Notes[i] = NULL;
- Titles[i-1] = strdup(title);
- Titles[i] = NULL;
- return sort_titles(i-1);
- }
-
-
- /*
- * unalloc_note ()
- */
- void
- unalloc_note(widget)
- Widget widget;
- {
- int i;
-
- i = 0;
- while (Notes[i]) {
- if (*Notes[i] == widget) {
- while (Notes[i+1]) {
- Notes[i] = Notes[i+1];
- Titles[i] = Titles[i+1];
- i++;
- }
- Notes[i] = NULL;
- Titles[i] = NULL;
- Notes = (Widget **) realloc(Notes, (i+1)*sizeof(char *));
- Titles = (char **) realloc(Titles, (i+1)*sizeof(char *));
- if (!Notes || !Titles)
- die("Realloc in unalloc_note failed.");
- return;
- }
- i++;
- }
- }
-
-
- /*
- * write_notefile ()
- */
- void
- write_notefile()
- {
- FILE *fp;
- int i;
- Dimension w, h;
- Position x, y;
- String title, text;
- XWindowAttributes atribs;
-
- if ((fp = fopen(notefile, "w")) == NULL)
- return;
-
- i = 0;
- while (Notes[i]) {
- XtVaGetValues(*Notes[i], XtNtitle, &title,
- XtNx, &x, XtNy, &y, NULL);
- XGetWindowAttributes(XtDisplay(*Notes[i]),
- XtWindow(*Notes[i]), &atribs);
- /*
- * this hack is the only way I know for now of eliminating
- * 'creeping' windows caused by the offset injected into
- * the x and y values of a window when they're mapped by
- * a window manager such as twm... there's undoubtedly
- * a more elegant approach, but I don't know how to
- * do it yet! :-)
- */
- if (atribs.map_state != IsUnmapped) {
- x -= H_OFFSET;
- y -= V_OFFSET;
- }
- XtVaGetValues(XtNameToWidget(*Notes[i], "*note"),
- XtNstring, &text, XtNwidth, &w, XtNheight, &h, NULL);
- fprintf(fp, "\f%d %d %d %d %s\n%s", x, y, w, h, title, text);
- i++;
- }
- fclose(fp);
- }
-
-
- /*
- * desensitize_start_button ()
- */
- static void
- desensitize_start_button(widget, client_data, call_data)
- Widget widget;
- XtPointer client_data, call_data;
- {
- Widget w;
-
- w = XtNameToWidget(toplevel, "*start_button");
- if (w)
- XtVaSetValues(w, XtNsensitive, False, NULL);
- }
-
-
- /*
- * sensitize_start_button ()
- */
- void
- sensitize_start_button(widget, client_data, call_data)
- Widget widget;
- XtPointer client_data, call_data;
- {
- Widget w;
-
- w = XtNameToWidget(toplevel, "*start_button");
- if (w)
- XtVaSetValues(w, XtNsensitive, True, NULL);
- }
-
- /*
- * version ()
- */
- static void
- version(widget, client_data, call_data)
- Widget widget;
- XtPointer client_data, call_data;
- {
- Widget w, popup, form, prompt, dismiss_button;
- static char tmp[BUFSIZ];
- Position top_w, pop_w, x, y;
-
- desensitize_start_button();
-
- popup = XtCreatePopupShell("Version",
- transientShellWidgetClass, toplevel,
- NULL, ZERO);
-
- form = XtCreateManagedWidget("form",
- formWidgetClass, popup,
- NULL, ZERO);
-
- sprintf(tmp, "Notes v%d.%d.%d\nby %s",
- VERSION, SUBVERSION, PATCHLEVEL, AUTHOR);
- prompt = XtVaCreateManagedWidget("prompt",
- labelWidgetClass, form,
- XtNlabel, tmp,
- XtNborderWidth, 0,
- XtNtop, XawChainTop,
- XtNbottom, XawChainTop,
- XtNleft, XawChainLeft,
- XtNright, XawChainLeft,
- NULL);
-
- dismiss_button = XtVaCreateManagedWidget("dismiss_button",
- commandWidgetClass, form,
- XtNlabel, "Dismiss",
- XtNwidth, 64,
- XtNfromVert, prompt,
- XtNtop, XawChainBottom,
- XtNbottom, XawChainBottom,
- XtNleft, XawChainLeft,
- XtNright, XawChainLeft,
- NULL);
- AddCallback(dismiss_button, destroy_widget, NULL);
- AddCallback(dismiss_button, sensitize_start_button, NULL);
-
- XtRealizeWidget(popup);
-
- XtVaGetValues(toplevel, XtNwidth, &top_w, NULL);
- XtVaGetValues(popup, XtNwidth, &pop_w, NULL);
- XtTranslateCoords(toplevel, (top_w-pop_w)/2, 0, &x, &y);
- XtVaSetValues(popup, XtNx, x, XtNy, y, NULL);
-
- XtPopup(popup, XtGrabNone);
- }
-
-
- /*
- * main ()
- */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- Widget start_button;
-
- toplevel = XtAppInitialize(&app_con, "notes",
- NULL, ZERO, /* options, option count */
- &argc, argv, /* command line options */
- fallback_resources, /* fallback resources */
- NULL, ZERO); /* other args */
-
- XtAppAddActions(app_con, actionTable, XtNumber(actionTable));
-
- start_button = XtCreateManagedWidget("start_button",
- commandWidgetClass, toplevel,
- NULL, ZERO);
- AddCallback(start_button, desensitize_start_button, NULL);
- AddCallback(start_button, show_list, NULL);
-
- XtRealizeWidget(toplevel);
- read_notefile();
- XtAppMainLoop(app_con);
- }
-