Better icon alignment
[rmail.git] / src / utils / test_list_x11.c
blob25bf197bc205cff8423b833e7efd2b58d6262d09
1 #define _BSD_SOURCE
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <dirent.h>
8 #include <errno.h>
9 #include <fcntl.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
14 #include <X11/Intrinsic.h>
15 #include <X11/StringDefs.h>
16 #include <X11/Shell.h>
18 #include <X11/Xaw/Form.h>
19 #include <X11/Xaw/Viewport.h>
20 #include <X11/Xaw/Command.h>
22 #include <X11/Xaw/Label.h>
23 #include <X11/Xaw/Box.h>
25 #include "md5_utils.h"
26 #include "string_utils.h"
27 #include "file_utils.h"
28 #include "rfc5322.h"
29 #include "icons_utils.h"
31 #include "iv_widget.h"
33 #include "list.h"
35 struct applet {
36 XtAppContext ctx; /* Application context */
37 Widget shell; /* Application shell widget */
38 Widget form; /* Application top Form widget */
41 static struct mail_list *mlist;
43 #define FROM_ADDRESS_VALID (1 << 0)
44 #define REPLY_TO_VALID (1 << 1)
45 #define SUBJECT_VALID (1 << 2)
47 void list_add_from_file(const char *filename)
49 FILE *fh;
50 int done = 0;
51 char buf[1024]; /* 998 + CR + LF + PADDING */
52 struct mail_entry entry;
54 /* Check if is a regular file */
55 if (file_type(filename)) {
56 return;
59 fh = fopen(filename, "r");
60 if (!fh)
61 return;
63 while (fgets(buf, sizeof(buf), fh)) {
64 if (!strncmp(buf, "From:", 5)) {
65 if (!rfc5322_extract_address(entry.addr, buf, 1024)) {
66 done |= FROM_ADDRESS_VALID;
68 } else if (!strncmp(buf, "Reply-to:", 9)) {
69 if (done & FROM_ADDRESS_VALID)
70 continue;
72 if (!rfc5322_extract_address(entry.addr, buf, 1024)) {
73 done |= REPLY_TO_VALID;
75 } else if (!strncmp(buf, "Subject:", 8)) {
76 rfc5322_extract_subject(entry.subj, buf, 1024);
77 done |= SUBJECT_VALID;
78 } else {
79 #if 0
80 printf("[SKIP] ------- %s", buf);
81 #endif
84 /* Exits loop if all fields are valid */
85 if (((done & FROM_ADDRESS_VALID) || (done & REPLY_TO_VALID)) &&
86 (done & SUBJECT_VALID)) {
87 break;
90 fclose(fh);
92 if (done && mlist) {
93 strncpy(entry.name, filename, 1024);
94 md5_calc_sum(entry.addr, entry.addr_md5);
96 /* Update List */
97 if (list_add_entry(mlist, &entry)) {
98 fprintf(stderr, "%s - No free slot for %s\n", __func__, filename);
99 } else {
100 /*fprintf(stderr, "%s - File %s added to list\n", __func__, filename);*/
106 /*======================================================================*/
107 /* X11 CODE */
108 /*======================================================================*/
110 /* The callback function for the quit button. */
111 void quit_callback(Widget w,
112 __attribute__((unused)) XtPointer client_data,
113 __attribute__((unused)) XtPointer call_data)
115 list_free(mlist);
117 XtDestroyApplicationContext(XtWidgetToApplicationContext(w));
119 exit(0);
122 static void fix_scrollbar_translations(Widget w, String name)
124 Widget sb = NULL; /* scrollbar widget */
126 /* New scrollbar translation */
127 String trans = "#override "
128 "<Btn1Down>: StartScroll(Forward)\n" /* Left button */
129 "<Btn2Down>: \n" /* Middle button */
130 "<Btn3Down>: StartScroll(Backward)\n" /* Right button */
131 "<Btn4Down>: StartScroll(Backward)\n" /* Wheel down */
132 "<Btn5Down>: StartScroll(Forward)\n" /* Wheel up */
133 "<Btn1Motion>: MoveThumb() NotifyThumb()\n"
134 "<BtnUp>: NotifyScroll(Proportional) EndScroll()";
136 if (!name)
137 return;
139 sb = XtNameToWidget(w, name);
140 if (sb)
141 XtOverrideTranslations(sb, XtParseTranslationTable(trans));
142 else
143 printf("%s: WARNING cannon set %s translation!\n", __func__, name);
147 static int create_applet(struct applet *app, int argc, char **argv)
149 XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL);
151 /* Open Xt application shell widget */
152 app->shell = XtVaOpenApplication(&app->ctx, "Applet_X11_List_Mail", NULL, 0,
153 &argc, argv, NULL,
154 applicationShellWidgetClass,
155 NULL);
157 /* Create top form widget */
158 app->form = XtVaCreateManagedWidget("AppForm", formWidgetClass,
159 app->shell, NULL);
160 return 0;
163 /* The callback function for the quit button. */
164 void item_callback(__attribute__((unused)) Widget w,
165 XtPointer item_string,
166 __attribute__((unused)) XtPointer call_data)
168 fprintf(stderr, "%s\n", (char *) item_string);
171 static int list_add_item(Widget parent, const struct mail_entry *item)
173 Display *d;
174 Visual *visual;
175 int screen;
177 /* Depth of the root window */
178 int depth;
180 char *icon = NULL;
181 XImage *pix = NULL;
183 Widget box_v;
184 Widget box_h;
185 Widget addr;
186 Widget subj;
187 Widget iv;
189 d = XtDisplay(parent);
191 screen = DefaultScreen(d);
192 depth = DisplayPlanes(d, screen);
193 visual = XDefaultVisual(d, screen);
195 icon = icon_get_path((char *) item->addr_md5);
197 box_h = XtVaCreateManagedWidget("box_h", boxWidgetClass, parent,
198 XtNorientation, XtorientHorizontal,
199 NULL);
201 pix = create_ximage_from_PNG(d, visual, depth, icon, NULL);
202 iv = XtVaCreateManagedWidget("IV", imageViewWidgetClass, box_h,
203 XtNximage, pix,
204 XtNimageType, 0,
205 NULL);
207 box_v = XtVaCreateManagedWidget("box_v", boxWidgetClass, box_h,
208 XtNorientation, XtorientVertical,
209 NULL);
211 addr = XtVaCreateManagedWidget("from", labelWidgetClass, box_v,
212 XtNborderWidth, 0,
213 XtNwidth, 400,
214 XtNlabel, item->addr,
215 XtNjustify, XtJustifyLeft,
216 NULL);
218 subj = XtVaCreateManagedWidget("subj", labelWidgetClass, box_v,
219 XtNborderWidth, 0,
220 XtNwidth, 400,
221 XtNlabel, item->subj,
222 XtNjustify, XtJustifyLeft,
223 NULL);
225 /* Set handler for mouse button press on widgets
226 * Pass the file to the callbacks
228 XtAddEventHandler(addr, ButtonPressMask, False, (XtEventHandler) item_callback, (XtPointer) item->name);
229 XtAddEventHandler(subj, ButtonPressMask, False, (XtEventHandler) item_callback, (XtPointer) item->name);
230 XtAddEventHandler(iv, ButtonPressMask, False, (XtEventHandler) item_callback, (XtPointer) item->name);
232 /* Free allocated icon pathname with 'icon_get_path()' */
233 icon_free_path(icon);
235 return 0;
238 int xutil_main(struct mail_list *lst, int argc, char **argv)
240 size_t n;
241 int rc;
242 struct applet app;
244 Widget vport; /* ViewPort (list container) */
245 Widget button;
246 Widget box;
248 rc = create_applet(&app, argc, argv);
250 vport = XtVaCreateManagedWidget("vport", viewportWidgetClass,
251 app.form,
252 XtNresizable, False,
253 XtNwidth, 450,
254 XtNheight, 400,
255 XtNallowVert, True, /* Display Vertical scrollbar */
256 XtNallowHoriz, True, /* Display Horizontal scrollbar */
257 XtNuseBottom, True, /* Horizontal scrollbar at bottom */
258 XtNtop, XtChainTop,
259 NULL);
260 if (vport == NULL)
261 return -1;
263 box = XtVaCreateManagedWidget("box", boxWidgetClass, vport,
264 XtNorientation, XtorientVertical,
265 NULL);
267 if (lst) {
268 for (n = 0; n < lst->n; n++) {
269 list_add_item(box, &lst->list[n]);
273 button = XtVaCreateManagedWidget("quit", commandWidgetClass,
274 app.form,
275 XtNfromVert, vport,
276 XtNleft, XtChainLeft,
277 XtNright, XtChainLeft,
278 XtNtop, XtChainBottom,
279 XtNbottom, XtChainBottom,
280 XtNresizable, False,
281 NULL);
283 XtAddCallback(button, XtNcallback, quit_callback, NULL);
285 XtRealizeWidget(app.shell);
287 /* Override default translations (A.k.a. bind actions to widgets) */
288 fix_scrollbar_translations(vport, "horizontal");
289 fix_scrollbar_translations(vport, "vertical");
291 XtAppMainLoop(app.ctx);
293 return 0;
296 /*======================================================================*/
297 /* END X11 CODE */
298 /*======================================================================*/
300 int main(int argc, char **argv)
302 int rc;
303 char old_path[PATH_MAX];
305 const char *path;
307 size_t n;
309 if (argc < 2) {
310 path = "/home/roberto/Maildir/cur/";
311 } else {
312 path = argv[1];
315 if (!getcwd(old_path, PATH_MAX)) {
316 fprintf(stderr, "%s - GETCWD: %s\n", __func__, strerror(errno));
317 return -1;
320 if (chdir(path) < 0) {
321 fprintf(stderr, "%s - CHDIR: %s\n", __func__, strerror(errno));
322 return -1;
325 n = dir_entries(path);
326 if (n < 1) {
327 fprintf(stderr, "%s is empty!\n", path);
328 rc = -1;
329 goto out_1;
332 /* Init mail list */
333 mlist = list_create(n, MESSAGE_LIMIT);
334 if (!mlist) {
335 rc = -1;
336 goto out_1;
339 fprintf(stderr, "Try to process %lu files\n", (unsigned long) mlist->n);
341 rc = scan_dir(path, list_add_from_file);
343 /*int*/ xutil_main(mlist, argc, argv);
345 list_free(mlist);
347 out_1:
348 if (chdir(old_path) < 0) {
349 fprintf(stderr, "%s - Cannot restore path %s!\n", __func__, strerror(errno));
352 return rc;