gprop.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /* Properties dialog for the Gnome edition of the Midnight Commander
  2. *
  3. * Copyright (C) 1998 The Free Software Foundation
  4. *
  5. * Author: Federico Mena <federico@nuclecu.unam.mx>
  6. *
  7. * Known bug: the problem with the multiple entries in the Properties
  8. * is a problem with the hisotry code.
  9. */
  10. #include <grp.h>
  11. #include <pwd.h>
  12. #include <sys/types.h>
  13. #include <gnome.h>
  14. #include "gprop.h"
  15. static GtkWidget *
  16. label_new (char *text, double xalign, double yalign)
  17. {
  18. GtkWidget *label;
  19. label = gtk_label_new (text);
  20. gtk_misc_set_alignment (GTK_MISC (label), xalign, yalign);
  21. gtk_widget_show (label);
  22. return label;
  23. }
  24. static void
  25. free_stuff (GtkWidget *widget, gpointer data)
  26. {
  27. if (data)
  28. g_free (data);
  29. }
  30. /***** Filename *****/
  31. GpropFilename *
  32. gprop_filename_new (char *complete_filename, char *filename)
  33. {
  34. GpropFilename *gp;
  35. GtkWidget *frame;
  36. GtkWidget *vbox;
  37. GtkWidget *hbox;
  38. char *s;
  39. g_return_val_if_fail (complete_filename != NULL, NULL);
  40. g_return_val_if_fail (filename != NULL, NULL);
  41. gp = g_new (GpropFilename, 1);
  42. gp->top = gtk_vbox_new (FALSE, 6);
  43. gtk_signal_connect (GTK_OBJECT (gp->top), "destroy",
  44. (GtkSignalFunc) free_stuff,
  45. gp);
  46. frame = gtk_frame_new (_("Filename"));
  47. gtk_box_pack_start (GTK_BOX (gp->top), frame, FALSE, FALSE, 0);
  48. gtk_widget_show (frame);
  49. vbox = gtk_vbox_new (FALSE, 6);
  50. gtk_container_border_width (GTK_CONTAINER (vbox), 6);
  51. gtk_container_add (GTK_CONTAINER (frame), vbox);
  52. gtk_widget_show (vbox);
  53. s = g_copy_strings (_("Full name: "), complete_filename, NULL);
  54. gtk_box_pack_start (GTK_BOX (vbox), label_new (s, 0.0, 0.5), FALSE, FALSE, 0);
  55. g_free (s);
  56. hbox = gtk_hbox_new (FALSE, 6);
  57. gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  58. gtk_widget_show (hbox);
  59. gtk_box_pack_start (GTK_BOX (hbox), label_new (_("Filename"), 0.0, 0.5), FALSE, FALSE, 0);
  60. gp->filename = gnome_entry_new (NULL);
  61. gtk_entry_set_text (GTK_ENTRY (gnome_entry_gtk_entry (GNOME_ENTRY (gp->filename))), filename);
  62. gtk_box_pack_start (GTK_BOX (hbox), gp->filename, TRUE, TRUE, 0);
  63. gtk_widget_show (gp->filename);
  64. return gp;
  65. }
  66. void
  67. gprop_filename_get_data (GpropFilename *gp, char **filename)
  68. {
  69. GtkWidget *entry;
  70. g_return_if_fail (gp != NULL);
  71. if (filename) {
  72. entry = gnome_entry_gtk_entry (GNOME_ENTRY (gp->filename));
  73. *filename = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
  74. }
  75. }
  76. /* Executable */
  77. GpropExec *
  78. gprop_exec_new (GnomeDesktopEntry *dentry)
  79. {
  80. GpropExec *ge;
  81. GtkWidget *frame, *table;
  82. char *s;
  83. ge = g_new (GpropExec, 1);
  84. ge->top = gtk_vbox_new (FALSE, 6);
  85. frame = gtk_frame_new (_("Command"));
  86. gtk_box_pack_start (GTK_BOX (ge->top), frame, FALSE, FALSE, 0);
  87. gtk_widget_show (frame);
  88. table = gtk_table_new (0, 0, 0);
  89. gtk_container_border_width (GTK_CONTAINER (table), 6);
  90. gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  91. gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  92. gtk_container_add (GTK_CONTAINER (frame), table);
  93. gtk_table_attach (GTK_TABLE (table), label_new (_("Command:"), 0.0, 0.5),
  94. 0, 1, 0, 1,
  95. GTK_FILL, GTK_FILL, 0, 0);
  96. ge->entry = gnome_entry_new (NULL);
  97. s = gnome_config_assemble_vector (dentry->exec_length, (const char * const *) dentry->exec);
  98. gtk_entry_set_text (GTK_ENTRY (gnome_entry_gtk_entry (GNOME_ENTRY (ge->entry))), s);
  99. g_free (s);
  100. gtk_table_attach (GTK_TABLE (table), ge->entry,
  101. 1, 2, 0, 1, 0, 0, 0, 0);
  102. ge->check = gtk_check_button_new_with_label (_("Use terminal"));
  103. GTK_TOGGLE_BUTTON (ge->check)->active = dentry->terminal ? 1 : 0;
  104. gtk_table_attach (GTK_TABLE (table), ge->check,
  105. 1, 2, 1, 2, 0, 0, 0, 0);
  106. gtk_widget_show_all (ge->top);
  107. return ge;
  108. }
  109. void
  110. gprop_exec_get_data (GpropExec *ge, GnomeDesktopEntry *dentry)
  111. {
  112. GtkEntry *entry;
  113. entry = GTK_ENTRY (gnome_entry_gtk_entry (GNOME_ENTRY (ge->entry)));
  114. g_strfreev (dentry->exec);
  115. gnome_config_make_vector (gtk_entry_get_text (entry),
  116. &dentry->exec_length, &dentry->exec);
  117. dentry->terminal = GTK_TOGGLE_BUTTON (ge->check)->active;
  118. }
  119. /***** permissions *****/
  120. static umode_t
  121. perm_get_umode (GpropPerm *gp)
  122. {
  123. umode_t umode;
  124. #define SETBIT(widget, flag) umode |= GTK_TOGGLE_BUTTON (widget)->active ? flag : 0
  125. umode = 0;
  126. SETBIT (gp->suid, S_ISUID);
  127. SETBIT (gp->sgid, S_ISGID);
  128. SETBIT (gp->svtx, S_ISVTX);
  129. SETBIT (gp->rusr, S_IRUSR);
  130. SETBIT (gp->wusr, S_IWUSR);
  131. SETBIT (gp->xusr, S_IXUSR);
  132. SETBIT (gp->rgrp, S_IRGRP);
  133. SETBIT (gp->wgrp, S_IWGRP);
  134. SETBIT (gp->xgrp, S_IXGRP);
  135. SETBIT (gp->roth, S_IROTH);
  136. SETBIT (gp->woth, S_IWOTH);
  137. SETBIT (gp->xoth, S_IXOTH);
  138. return umode;
  139. #undef SETBIT
  140. }
  141. static void
  142. perm_set_mode_label (GtkWidget *widget, gpointer data)
  143. {
  144. umode_t umode;
  145. GpropPerm *gp;
  146. char s_mode[5];
  147. gp = data;
  148. umode = perm_get_umode (gp);
  149. s_mode[0] = '0' + ((umode & (S_ISUID | S_ISGID | S_ISVTX)) >> 9);
  150. s_mode[1] = '0' + ((umode & (S_IRUSR | S_IWUSR | S_IXUSR)) >> 6);
  151. s_mode[2] = '0' + ((umode & (S_IRGRP | S_IWGRP | S_IXGRP)) >> 3);
  152. s_mode[3] = '0' + ((umode & (S_IROTH | S_IWOTH | S_IXOTH)) >> 0);
  153. s_mode[4] = 0;
  154. gtk_label_set (GTK_LABEL (gp->mode_label), s_mode);
  155. }
  156. static GtkWidget *
  157. perm_check_new (char *text, int state, GpropPerm *gp)
  158. {
  159. GtkWidget *check;
  160. if (text)
  161. check = gtk_check_button_new_with_label (text);
  162. else
  163. check = gtk_check_button_new ();
  164. gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (check), FALSE);
  165. gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (check), state ? TRUE : FALSE);
  166. gtk_signal_connect (GTK_OBJECT (check), "toggled",
  167. (GtkSignalFunc) perm_set_mode_label,
  168. gp);
  169. gtk_widget_show (check);
  170. return check;
  171. }
  172. #define ATTACH(table, widget, left, right, top, bottom) \
  173. gtk_table_attach (GTK_TABLE (table), widget, \
  174. left, right, top, bottom, \
  175. GTK_FILL | GTK_SHRINK, \
  176. GTK_FILL | GTK_SHRINK, \
  177. 0, 0);
  178. #define PERMSET(name, r, w, x, rmask, wmask, xmask, y) do { \
  179. r = perm_check_new (NULL, umode & rmask, gp); \
  180. w = perm_check_new (NULL, umode & wmask, gp); \
  181. x = perm_check_new (NULL, umode & xmask, gp); \
  182. \
  183. ATTACH (table, label_new (name, 0.0, 0.5), 0, 1, y, y + 1); \
  184. ATTACH (table, r, 1, 2, y, y + 1); \
  185. ATTACH (table, w, 2, 3, y, y + 1); \
  186. ATTACH (table, x, 3, 4, y, y + 1); \
  187. } while (0);
  188. static GtkWidget *
  189. perm_mode_new (GpropPerm *gp, umode_t umode)
  190. {
  191. GtkWidget *frame;
  192. GtkWidget *vbox;
  193. GtkWidget *hbox;
  194. GtkWidget *table;
  195. frame = gtk_frame_new (_("File mode (permissions)"));
  196. vbox = gtk_vbox_new (FALSE, 4);
  197. gtk_container_border_width (GTK_CONTAINER (vbox), 6);
  198. gtk_container_add (GTK_CONTAINER (frame), vbox);
  199. gtk_widget_show (vbox);
  200. hbox = gtk_hbox_new (FALSE, 0);
  201. gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  202. gtk_widget_show (hbox);
  203. gtk_box_pack_start (GTK_BOX (hbox), label_new (_("Current mode: "), 0.0, 0.5), FALSE, FALSE, 0);
  204. gp->mode_label = label_new ("0000", 0.0, 0.5);
  205. gtk_box_pack_start (GTK_BOX (hbox), gp->mode_label, FALSE, FALSE, 0);
  206. table = gtk_table_new (4, 5, FALSE);
  207. gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  208. gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  209. gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  210. gtk_widget_show (table);
  211. /* Headings */
  212. ATTACH (table, label_new (_("Read"), 0.0, 0.5), 1, 2, 0, 1);
  213. ATTACH (table, label_new (_("Write"), 0.0, 0.5), 2, 3, 0, 1);
  214. ATTACH (table, label_new (_("Exec"), 0.0, 0.5), 3, 4, 0, 1);
  215. ATTACH (table, label_new (_("Special"), 0.0, 0.5), 4, 5, 0, 1);
  216. /* Permissions */
  217. PERMSET (_("User"), gp->rusr, gp->wusr, gp->xusr, S_IRUSR, S_IWUSR, S_IXUSR, 1);
  218. PERMSET (_("Group"), gp->rgrp, gp->wgrp, gp->xgrp, S_IRGRP, S_IWGRP, S_IXGRP, 2);
  219. PERMSET (_("Other"), gp->roth, gp->woth, gp->xoth, S_IROTH, S_IWOTH, S_IXOTH, 3);
  220. /* Special */
  221. gp->suid = perm_check_new (_("Set UID"), umode & S_ISUID, gp);
  222. gp->sgid = perm_check_new (_("Set GID"), umode & S_ISGID, gp);
  223. gp->svtx = perm_check_new (_("Sticky"), umode & S_ISVTX, gp);
  224. ATTACH (table, gp->suid, 4, 5, 1, 2);
  225. ATTACH (table, gp->sgid, 4, 5, 2, 3);
  226. ATTACH (table, gp->svtx, 4, 5, 3, 4);
  227. perm_set_mode_label (NULL, gp);
  228. return frame;
  229. }
  230. #undef ATTACH
  231. #undef PERMSET
  232. static GtkWidget *
  233. perm_owner_new (char *owner)
  234. {
  235. GtkWidget *gentry;
  236. GtkWidget *entry;
  237. GtkWidget *list;
  238. struct passwd *passwd;
  239. int i, sel;
  240. gentry = gnome_entry_new (NULL);
  241. list = GTK_COMBO (gentry)->list;
  242. /* We can't use 0 as the intial element because the gnome entry may already
  243. * have loaded some history from a file.
  244. */
  245. i = g_list_length (GTK_LIST (list)->children);
  246. sel = i;
  247. gnome_entry_append_history (GNOME_ENTRY (gentry), FALSE, _("<Unknown>"));
  248. for (setpwent (); (passwd = getpwent ()) != NULL; i++) {
  249. gnome_entry_append_history (GNOME_ENTRY (gentry), FALSE, passwd->pw_name);
  250. if (strcmp (passwd->pw_name, owner) == 0)
  251. sel = i;
  252. }
  253. endpwent ();
  254. gtk_list_select_item (GTK_LIST (list), sel);
  255. entry = gnome_entry_gtk_entry (GNOME_ENTRY (gentry));
  256. gtk_entry_set_text (GTK_ENTRY (entry), owner);
  257. return gentry;
  258. }
  259. static GtkWidget *
  260. perm_group_new (char *group)
  261. {
  262. GtkWidget *gentry;
  263. GtkWidget *entry;
  264. GtkWidget *list;
  265. struct group *grp;
  266. int i, sel;
  267. gentry = gnome_entry_new ("gprop_perm_group");
  268. gnome_entry_append_history (GNOME_ENTRY (gentry), FALSE, _("<Unknown>"));
  269. list = GTK_COMBO (gentry)->list;
  270. /* We can't use 0 as the intial element because the gnome entry may already
  271. * have loaded some history from a file.
  272. */
  273. i = g_list_length (GTK_LIST (list)->children);
  274. sel = i;
  275. for (setgrent (); (grp = getgrent ()) != NULL; i++) {
  276. gnome_entry_append_history (GNOME_ENTRY (gentry), FALSE, grp->gr_name);
  277. if (strcmp (grp->gr_name, group) == 0)
  278. sel = i;
  279. }
  280. endgrent ();
  281. gtk_list_select_item (GTK_LIST (list), sel);
  282. entry = gnome_entry_gtk_entry (GNOME_ENTRY (gentry));
  283. gtk_entry_set_text (GTK_ENTRY (entry), group);
  284. return gentry;
  285. }
  286. static GtkWidget *
  287. perm_ownership_new (GpropPerm *gp, char *owner, char *group)
  288. {
  289. GtkWidget *frame;
  290. GtkWidget *table;
  291. frame = gtk_frame_new ("File ownership");
  292. table = gtk_table_new (2, 2, FALSE);
  293. gtk_container_border_width (GTK_CONTAINER (table), 6);
  294. gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  295. gtk_table_set_row_spacings (GTK_TABLE (table), 4);
  296. gtk_container_add (GTK_CONTAINER (frame), table);
  297. gtk_widget_show (table);
  298. /* Owner */
  299. gtk_table_attach (GTK_TABLE (table), label_new (_("Owner"), 0.0, 0.5),
  300. 0, 1, 0, 1,
  301. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK,
  302. 0, 0);
  303. gp->owner = perm_owner_new (owner);
  304. gtk_table_attach (GTK_TABLE (table), gp->owner,
  305. 1, 2, 0, 1,
  306. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  307. GTK_FILL | GTK_SHRINK,
  308. 0, 0);
  309. gtk_widget_show (gp->owner);
  310. /* Group */
  311. gtk_table_attach (GTK_TABLE (table), label_new (_("Group"), 0.0, 0.5),
  312. 0, 1, 1, 2,
  313. GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK,
  314. 0, 0);
  315. gp->group = perm_group_new (group);
  316. gtk_table_attach (GTK_TABLE (table), gp->group,
  317. 1, 2, 1, 2,
  318. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  319. GTK_FILL | GTK_SHRINK,
  320. 0, 0);
  321. gtk_widget_show (gp->group);
  322. return frame;
  323. }
  324. GpropPerm *
  325. gprop_perm_new (umode_t umode, char *owner, char *group)
  326. {
  327. GpropPerm *gp;
  328. GtkWidget *w;
  329. g_return_val_if_fail (owner != NULL, NULL);
  330. g_return_val_if_fail (group != NULL, NULL);
  331. gp = g_new (GpropPerm, 1);
  332. gp->top = gtk_vbox_new (FALSE, 6);
  333. gtk_signal_connect (GTK_OBJECT (gp->top), "destroy",
  334. (GtkSignalFunc) free_stuff,
  335. gp);
  336. w = perm_mode_new (gp, umode);
  337. gtk_box_pack_start (GTK_BOX (gp->top), w, FALSE, FALSE, 0);
  338. gtk_widget_show (w);
  339. w = perm_ownership_new (gp, owner, group);
  340. gtk_box_pack_start (GTK_BOX (gp->top), w, FALSE, FALSE, 0);
  341. gtk_widget_show (w);
  342. return gp;
  343. }
  344. void
  345. gprop_perm_get_data (GpropPerm *gp, umode_t *umode, char **owner, char **group)
  346. {
  347. g_return_if_fail (gp != NULL);
  348. if (umode)
  349. *umode = perm_get_umode (gp);
  350. if (owner)
  351. *owner = g_strdup (gtk_entry_get_text (GTK_ENTRY (gnome_entry_gtk_entry (GNOME_ENTRY (gp->owner)))));
  352. if (group)
  353. *group = g_strdup (gtk_entry_get_text (GTK_ENTRY (gnome_entry_gtk_entry (GNOME_ENTRY (gp->group)))));
  354. }
  355. /***** General *****/
  356. static void
  357. change_icon (GtkEntry *entry, GpropGeneral *gp)
  358. {
  359. char *filename;
  360. filename = gtk_entry_get_text (entry);
  361. if (g_file_exists (filename) && gp->icon_pixmap){
  362. gnome_pixmap_load_file (GNOME_PIXMAP (gp->icon_pixmap), gtk_entry_get_text (entry));
  363. }
  364. }
  365. GpropGeneral *
  366. gprop_general_new (char *title, char *icon_filename)
  367. {
  368. GpropGeneral *gp;
  369. GtkWidget *frame;
  370. GtkWidget *table;
  371. GtkWidget *entry;
  372. g_return_val_if_fail (title != NULL, NULL);
  373. g_return_val_if_fail (icon_filename != NULL, NULL);
  374. gp = g_new (GpropGeneral, 1);
  375. gp->top = gtk_vbox_new (FALSE, 6);
  376. gtk_signal_connect (GTK_OBJECT (gp->top), "destroy",
  377. (GtkSignalFunc) free_stuff,
  378. gp);
  379. frame = gtk_frame_new (_("General"));
  380. gtk_box_pack_start (GTK_BOX (gp->top), frame, FALSE, FALSE, 0);
  381. gtk_widget_show (frame);
  382. table = gtk_table_new (3, 2, FALSE);
  383. gtk_container_border_width (GTK_CONTAINER (table), 6);
  384. gtk_table_set_row_spacings (GTK_TABLE (table), 6);
  385. gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  386. gtk_container_add (GTK_CONTAINER (frame), table);
  387. gtk_widget_show (table);
  388. gtk_table_attach (GTK_TABLE (table), label_new (_("Title"), 0.0, 0.5),
  389. 0, 1, 0, 1,
  390. GTK_FILL | GTK_SHRINK,
  391. GTK_FILL | GTK_SHRINK,
  392. 0, 0);
  393. gp->title = gnome_entry_new ("gprop_general_title");
  394. entry = gnome_entry_gtk_entry (GNOME_ENTRY (gp->title));
  395. gtk_entry_set_text (GTK_ENTRY (entry), title);
  396. gtk_table_attach (GTK_TABLE (table), gp->title,
  397. 1, 2, 0, 1,
  398. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  399. GTK_FILL | GTK_SHRINK,
  400. 0, 0);
  401. gtk_widget_show (gp->title);
  402. gtk_table_attach (GTK_TABLE (table), label_new (_("Icon"), 0.0, 0.5),
  403. 0, 1, 1, 2,
  404. GTK_FILL | GTK_SHRINK,
  405. GTK_FILL | GTK_SHRINK,
  406. 0, 0);
  407. gp->icon_pixmap = gnome_pixmap_new_from_file (icon_filename);
  408. gtk_table_attach (GTK_TABLE (table), gp->icon_pixmap,
  409. 1, 2, 2, 3,
  410. GTK_FILL | GTK_SHRINK,
  411. GTK_FILL | GTK_SHRINK,
  412. 0, 0);
  413. gtk_widget_show (gp->icon_pixmap);
  414. gp->icon_filename = gnome_file_entry_new ("gprop_general_icon_filename", _("Select icon"));
  415. entry = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (gp->icon_filename));
  416. gtk_signal_connect (GTK_OBJECT (entry), "changed",
  417. (GtkSignalFunc) change_icon,
  418. gp);
  419. gtk_entry_set_text (GTK_ENTRY (entry), icon_filename);
  420. gtk_table_attach (GTK_TABLE (table), gp->icon_filename,
  421. 1, 2, 1, 2,
  422. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  423. GTK_FILL | GTK_SHRINK,
  424. 0, 0);
  425. gtk_widget_show (gp->icon_filename);
  426. return gp;
  427. }
  428. void
  429. gprop_general_get_data (GpropGeneral *gp, char **title, char **icon_filename)
  430. {
  431. GtkWidget *entry;
  432. g_return_if_fail (gp != NULL);
  433. if (title) {
  434. entry = gnome_entry_gtk_entry (GNOME_ENTRY (gp->title));
  435. *title = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
  436. }
  437. if (icon_filename) {
  438. entry = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (gp->icon_filename));
  439. *icon_filename = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
  440. }
  441. }