gscreen.c 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108
  1. /* GNU Midnight Commander -- GNOME edition
  2. *
  3. * Directory display routines
  4. *
  5. * Copyright (C) 1997 The Free Software Foundation
  6. *
  7. * Authors: Miguel de Icaza
  8. * Federico Mena
  9. */
  10. #include <config.h>
  11. #include <string.h>
  12. #include <stdlib.h> /* atoi */
  13. #include "fs.h"
  14. #include "mad.h"
  15. #include "x.h"
  16. #include "dir.h"
  17. #include "command.h"
  18. #include "panel.h"
  19. #define WANT_WIDGETS /* bleah */
  20. #include "main.h"
  21. #include "color.h"
  22. #include "mouse.h"
  23. #include "layout.h" /* get_panel_widget */
  24. #include "ext.h" /* regex_command */
  25. #include "cmd.h" /* copy_cmd, ren_cmd, delete_cmd, ... */
  26. #include "gscreen.h"
  27. #include "dir.h"
  28. #include "dialog.h"
  29. #include "gdesktop.h"
  30. #include "gdnd.h"
  31. #include "gtkdtree.h"
  32. #include "gpageprop.h"
  33. #include "gpopup.h"
  34. #include "gcliplabel.h"
  35. #include "gblist.h"
  36. #include "../vfs/vfs.h"
  37. #include <gdk/gdkprivate.h>
  38. /* The pixmaps */
  39. #include "directory.xpm"
  40. #include "link.xpm"
  41. #include "dev.xpm"
  42. #include "listing-list.xpm"
  43. #include "listing-iconic.xpm"
  44. /* This is used to initialize our pixmaps */
  45. static int pixmaps_ready;
  46. GdkPixmap *icon_directory_pixmap;
  47. GdkBitmap *icon_directory_mask;
  48. GdkPixmap *icon_link_pixmap;
  49. GdkBitmap *icon_link_mask;
  50. GdkPixmap *icon_dev_pixmap;
  51. GdkBitmap *icon_dev_mask;
  52. /* These are big images used in the Icon View, for the gnome_icon_list */
  53. static GdkImlibImage *icon_view_directory;
  54. static GdkImlibImage *icon_view_executable;
  55. static GdkImlibImage *icon_view_symlink;
  56. static GdkImlibImage *icon_view_device;
  57. static GdkImlibImage *icon_view_regular;
  58. static GdkImlibImage *icon_view_core;
  59. static GdkImlibImage *icon_view_sock;
  60. static GtkTargetEntry drag_types [] = {
  61. { "text/uri-list", 0, TARGET_URI_LIST },
  62. { "text/plain", 0, TARGET_TEXT_PLAIN }
  63. };
  64. static GtkTargetEntry drop_types [] = {
  65. { "text/uri-list", 0, TARGET_URI_LIST }
  66. };
  67. #define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
  68. /* GtkWidgets with the shaped windows for dragging */
  69. GtkWidget *drag_directory = NULL;
  70. GtkWidget *drag_directory_ok = NULL;
  71. GtkWidget *drag_multiple = NULL;
  72. GtkWidget *drag_multiple_ok = NULL;
  73. static void panel_file_list_configure_contents (GtkWidget *sw, WPanel *panel, int main_width, int height);
  74. #define CLIST_FROM_SW(panel_list) GTK_CLIST (GTK_BIN (panel_list)->child)
  75. void
  76. repaint_file (WPanel *panel, int file_index, int move, int attr, int isstatus)
  77. {
  78. }
  79. /*
  80. * Invoked by the generic code: show current working directory
  81. */
  82. void
  83. show_dir (WPanel *panel)
  84. {
  85. assign_text (panel->current_dir, panel->cwd);
  86. update_input (panel->current_dir, 1);
  87. gtk_window_set_title (GTK_WINDOW (panel->xwindow), panel->cwd);
  88. }
  89. /*
  90. * Utility routine: Try to load a bitmap for a file_entry
  91. */
  92. static void
  93. panel_file_list_set_type_bitmap (GtkCList *cl, int row, int column, int color, file_entry *fe)
  94. {
  95. /* Here, add more icons */
  96. switch (color){
  97. case DIRECTORY_COLOR:
  98. gtk_clist_set_pixmap (cl, row, column, icon_directory_pixmap, icon_directory_mask);
  99. break;
  100. case LINK_COLOR:
  101. gtk_clist_set_pixmap (cl, row, column, icon_link_pixmap, icon_link_mask);
  102. break;
  103. case DEVICE_COLOR:
  104. gtk_clist_set_pixmap (cl, row, column, icon_dev_pixmap, icon_dev_mask);
  105. break;
  106. }
  107. }
  108. /*
  109. * Sets the color attributes for a given row.
  110. */
  111. static void
  112. panel_file_list_set_row_colors (GtkCList *cl, int row, int color_pair)
  113. {
  114. gtk_clist_set_foreground (cl, row, gmc_color_pairs [color_pair].fore);
  115. gtk_clist_set_background (cl, row, gmc_color_pairs [color_pair].back);
  116. }
  117. /*
  118. * Update the status of the back and forward history buttons.
  119. * Called from the generic code
  120. */
  121. void
  122. x_panel_update_marks (WPanel *panel)
  123. {
  124. int ff = panel->dir_history->next ? 1 : 0;
  125. int bf = panel->dir_history->prev ? 1 : 0;
  126. if (!panel->fwd_b)
  127. return;
  128. gtk_widget_set_sensitive (panel->fwd_b, ff);
  129. gtk_widget_set_sensitive (panel->back_b, bf);
  130. }
  131. /*
  132. * Listing view: Load the contents
  133. */
  134. static void
  135. panel_fill_panel_list (WPanel *panel)
  136. {
  137. const int top = panel->count;
  138. const int items = panel->format->items;
  139. const int selected = panel->selected;
  140. GtkCList *cl = CLIST_FROM_SW (panel->list);
  141. int i, col, type_col, color;
  142. char **texts;
  143. texts = malloc (sizeof (char *) * items);
  144. gtk_clist_freeze (GTK_CLIST (cl));
  145. gtk_clist_clear (GTK_CLIST (cl));
  146. /* which column holds the type information */
  147. type_col = -1;
  148. for (i = 0; i < top; i++){
  149. file_entry *fe = &panel->dir.list [i];
  150. format_e *format = panel->format;
  151. for (col = 0; format; format = format->next){
  152. if (!format->use_in_gui)
  153. continue;
  154. if (type_col == -1)
  155. if (strcmp (format->id, "type") == 0)
  156. type_col = col;
  157. if (!format->string_fn)
  158. texts [col] = "";
  159. else
  160. texts [col] = (*format->string_fn)(fe, 10);
  161. col++;
  162. }
  163. gtk_clist_append (cl, texts);
  164. color = file_compute_color (fe->f.marked ? MARKED : NORMAL, fe);
  165. panel_file_list_set_row_colors (cl, i, color);
  166. if (type_col != -1)
  167. panel_file_list_set_type_bitmap (cl, i, type_col, color, fe);
  168. }
  169. /* This is needed as the gtk_clist_append changes selected under us :-( */
  170. panel->selected = selected;
  171. select_item (panel);
  172. gtk_clist_thaw (GTK_CLIST (cl));
  173. free (texts);
  174. }
  175. /*
  176. * Icon view: load the panel contents
  177. */
  178. static void
  179. panel_fill_panel_icons (WPanel *panel)
  180. {
  181. GnomeIconList *icons = GNOME_ICON_LIST (panel->icons);
  182. const int top = panel->count;
  183. const int selected = panel->selected;
  184. int i;
  185. GdkImlibImage *image;
  186. gnome_icon_list_freeze (icons);
  187. gnome_icon_list_clear (icons);
  188. for (i = 0; i < top; i++){
  189. file_entry *fe = &panel->dir.list [i];
  190. switch (file_entry_color (fe)){
  191. case DIRECTORY_COLOR:
  192. image = icon_view_directory;
  193. break;
  194. case LINK_COLOR:
  195. image = icon_view_symlink;
  196. break;
  197. case DEVICE_COLOR:
  198. image = icon_view_device;
  199. break;
  200. case SPECIAL_COLOR:
  201. image = icon_view_sock;
  202. break;
  203. case EXECUTABLE_COLOR:
  204. image = icon_view_executable;
  205. break;
  206. case CORE_COLOR:
  207. image = icon_view_core;
  208. break;
  209. case STALLED_COLOR:
  210. case NORMAL_COLOR:
  211. default:
  212. image = icon_view_regular;
  213. }
  214. gnome_icon_list_append_imlib (icons, image, fe->fname);
  215. }
  216. /* This is needed as the gtk_clist_append changes selected under us :-( */
  217. panel->selected = selected;
  218. gnome_icon_list_thaw (icons);
  219. select_item (panel);
  220. }
  221. /*
  222. * Invoked from the generic code to fill the display
  223. */
  224. void
  225. x_fill_panel (WPanel *panel)
  226. {
  227. if (panel->list_type == list_icons)
  228. panel_fill_panel_icons (panel);
  229. else
  230. panel_fill_panel_list (panel);
  231. gtk_signal_handler_block_by_data (GTK_OBJECT (panel->tree), panel);
  232. gtk_dtree_select_dir (GTK_DTREE (panel->tree), panel->cwd);
  233. gtk_signal_handler_unblock_by_data (GTK_OBJECT (panel->tree), panel);
  234. }
  235. static void
  236. gmc_panel_set_size (int index, int boot)
  237. {
  238. Widget *w;
  239. WPanel *p;
  240. w = (Widget *) get_panel_widget (index);
  241. p = (WPanel *) w;
  242. w->cols = 40;
  243. w->lines = 25;
  244. set_panel_formats (p);
  245. paint_panel (p);
  246. if (!boot)
  247. paint_frame (p);
  248. x_fill_panel (p);
  249. }
  250. void
  251. x_panel_set_size (int index)
  252. {
  253. printf ("WARNING: set size called\n");
  254. gmc_panel_set_size (index, 1);
  255. }
  256. /*
  257. * Invoked when the f.mark field of a file item changes
  258. */
  259. void
  260. x_panel_select_item (WPanel *panel, int index, int value)
  261. {
  262. int color;
  263. color = file_compute_color (value ? MARKED : NORMAL, &panel->dir.list[index]);
  264. panel_file_list_set_row_colors (CLIST_FROM_SW (panel->list), index, color);
  265. }
  266. void
  267. x_select_item (WPanel *panel)
  268. {
  269. if (panel->list_type == list_icons){
  270. GnomeIconList *list = GNOME_ICON_LIST (panel->icons);
  271. do_file_mark (panel, panel->selected, 1);
  272. display_mini_info (panel);
  273. gnome_icon_list_select_icon (list, panel->selected);
  274. if (list->icon_list){
  275. if (gnome_icon_list_icon_is_visible (list, panel->selected) != GTK_VISIBILITY_FULL)
  276. gnome_icon_list_moveto (list, panel->selected, 0.5);
  277. }
  278. gnome_canvas_update_now (GNOME_CANVAS (list));
  279. } else {
  280. GtkCList *clist = CLIST_FROM_SW (panel->list);
  281. int color, marked;
  282. if (panel->dir.list [panel->selected].f.marked)
  283. marked = 1;
  284. else
  285. marked = 0;
  286. color = file_compute_color (marked ? MARKED_SELECTED : SELECTED, &panel->dir.list [panel->selected]);
  287. panel_file_list_set_row_colors (CLIST_FROM_SW (panel->list), panel->selected, color);
  288. /* Make it visible */
  289. if (gtk_clist_row_is_visible (clist, panel->selected) != GTK_VISIBILITY_FULL)
  290. gtk_clist_moveto (clist, panel->selected, 0, 0.5, 0.0);
  291. }
  292. }
  293. void
  294. x_unselect_item (WPanel *panel)
  295. {
  296. if (panel->list_type == list_icons){
  297. int selected = panel->selected;
  298. /* This changes the panel->selected */
  299. gnome_icon_list_unselect_all (GNOME_ICON_LIST (panel->icons), NULL, NULL);
  300. panel->selected = selected;
  301. } else {
  302. int color;
  303. int val;
  304. val = panel->dir.list [panel->selected].f.marked ? MARKED : NORMAL;
  305. color = file_compute_color (val, &panel->dir.list [panel->selected]);
  306. panel_file_list_set_row_colors (CLIST_FROM_SW (panel->list), panel->selected, color);
  307. }
  308. }
  309. void
  310. x_filter_changed (WPanel *panel)
  311. {
  312. assign_text (panel->filter_w, panel->filter ? panel->filter : "");
  313. update_input (panel->filter_w, 1);
  314. }
  315. void
  316. x_adjust_top_file (WPanel *panel)
  317. {
  318. /* gtk_clist_moveto (GTK_CLIST (panel->list), panel->top_file, 0, 0.0, 0.0); */
  319. }
  320. /*
  321. * These two constants taken from Gtk sources, hack to figure out how much
  322. * of the clist is visible
  323. */
  324. #define COLUMN_INSET 3
  325. #define CELL_SPACING 1
  326. /*
  327. * Configures the columns title sizes for the panel->list CList widget
  328. */
  329. static void
  330. panel_file_list_configure_contents (GtkWidget *sw, WPanel *panel, int main_width, int height)
  331. {
  332. GtkCList *clist;
  333. format_e *format = panel->format;
  334. int i, used_columns, expandables, items;
  335. int char_width, usable_pixels, extra_pixels, width;
  336. int total_columns, extra_columns;
  337. int expand_space, extra_space, shrink_space;
  338. int lost_pixels, display_the_mini_info;
  339. /* Pass 1: Count minimum columns,
  340. * set field_len to default to the requested_field_len
  341. * and compute how much space we lost to the column decorations
  342. */
  343. lost_pixels = used_columns = expandables = items = 0;
  344. for (format = panel->format; format; format = format->next) {
  345. format->field_len = format->requested_field_len;
  346. if (!format->use_in_gui)
  347. continue;
  348. used_columns += format->field_len;
  349. items++;
  350. if (format->expand)
  351. expandables++;
  352. lost_pixels += CELL_SPACING + (2 * COLUMN_INSET);
  353. }
  354. /* The left scrollbar might take some space from us, use this information */
  355. if (GTK_WIDGET_VISIBLE (GTK_SCROLLED_WINDOW (sw)->vscrollbar)) {
  356. int scrollbar_width = GTK_WIDGET (GTK_SCROLLED_WINDOW (sw)->vscrollbar)->requisition.width;
  357. int scrollbar_space = GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (sw)->klass)->scrollbar_spacing;
  358. lost_pixels += scrollbar_space + scrollbar_width;
  359. }
  360. char_width = gdk_string_width (sw->style->font, "xW") / 2;
  361. width = main_width - lost_pixels;
  362. extra_pixels = width % char_width;
  363. usable_pixels = width - extra_pixels;
  364. total_columns = usable_pixels / char_width;
  365. extra_columns = total_columns - used_columns;
  366. if (extra_columns > 0) {
  367. expand_space = extra_columns / expandables;
  368. extra_space = extra_columns % expandables;
  369. } else
  370. extra_space = expand_space = 0;
  371. /*
  372. * Hack: the default mini-info display only gets displayed
  373. * if panel->estimated_total is not zero, ie, if this has been
  374. * initialized for the first time.
  375. */
  376. display_the_mini_info = (panel->estimated_total == 0);
  377. panel->estimated_total = total_columns;
  378. if (display_the_mini_info)
  379. display_mini_info (panel);
  380. /* If we dont have enough space, shorten the fields */
  381. if (used_columns > total_columns) {
  382. expand_space = 0;
  383. shrink_space = (used_columns - total_columns) / items;
  384. } else
  385. shrink_space = 0;
  386. clist = CLIST_FROM_SW (sw);
  387. gtk_clist_freeze (clist);
  388. for (i = 0, format = panel->format; format; format = format->next) {
  389. if (!format->use_in_gui)
  390. continue;
  391. format->field_len += (format->expand ? expand_space : 0) - shrink_space;
  392. gtk_clist_set_column_width (clist, i, format->field_len * char_width);
  393. i++;
  394. }
  395. gtk_clist_thaw (clist);
  396. }
  397. static void
  398. internal_select_item (GtkWidget *file_list, WPanel *panel, int row)
  399. {
  400. unselect_item (panel);
  401. panel->selected = row;
  402. select_item (panel);
  403. }
  404. static void
  405. panel_file_list_select_row (GtkWidget *file_list, int row, int column, GdkEvent *event, WPanel *panel)
  406. {
  407. int current_selection = panel->selected;
  408. printf ("Selecting %d %p, %d\n", row, event, event ? event->type : -1);
  409. if (!event) {
  410. internal_select_item (file_list, panel, row);
  411. return;
  412. }
  413. switch (event->type) {
  414. case GDK_BUTTON_RELEASE:
  415. printf ("1\n");
  416. gtk_clist_unselect_row (CLIST_FROM_SW (panel->list), row, 0);
  417. internal_select_item (file_list, panel, row);
  418. switch (event->button.button) {
  419. case 1:
  420. if (!(event->button.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)))
  421. break;
  422. /* fallback if shift-click is pressed */
  423. do_file_mark_range (panel, row, current_selection);
  424. break;
  425. case 2:
  426. do_file_mark (panel, row, !panel->dir.list[row].f.marked);
  427. break;
  428. case 3:
  429. /* FIXME: this should happen on button press, not button release */
  430. gpopup_do_popup ((GdkEventButton *) event, panel, row, panel->dir.list[row].fname);
  431. break;
  432. }
  433. break;
  434. case GDK_2BUTTON_PRESS:
  435. gtk_clist_unselect_row (CLIST_FROM_SW (panel->list), row, 0);
  436. if (event->button.button == 1)
  437. do_enter (panel);
  438. break;
  439. default:
  440. break;
  441. }
  442. }
  443. /* Figure out the number of visible lines in the panel */
  444. static void
  445. panel_file_list_compute_lines (GtkScrolledWindow *sw, WPanel *panel, int height)
  446. {
  447. int lost_pixels = 0;
  448. if (GTK_WIDGET_VISIBLE (sw->hscrollbar)) {
  449. int scrollbar_width = GTK_WIDGET (sw->hscrollbar)->requisition.width;
  450. int scrollbar_space = GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (sw)->klass)->scrollbar_spacing;
  451. lost_pixels = scrollbar_space + scrollbar_width;
  452. }
  453. panel->widget.lines = (height-lost_pixels) / (CLIST_FROM_SW (sw)->row_height + CELL_SPACING);
  454. }
  455. static void
  456. panel_file_list_size_allocate_hook (GtkWidget *sw, GtkAllocation *allocation, WPanel *panel)
  457. {
  458. gtk_signal_handler_block_by_data (GTK_OBJECT (sw), panel);
  459. panel_file_list_configure_contents (sw, panel, allocation->width, allocation->height);
  460. gtk_signal_handler_unblock_by_data (GTK_OBJECT (sw), panel);
  461. panel_file_list_compute_lines (GTK_SCROLLED_WINDOW (sw), panel, allocation->height);
  462. }
  463. static void
  464. panel_file_list_column_callback (GtkWidget *widget, int col, WPanel *panel)
  465. {
  466. format_e *format;
  467. int i;
  468. for (i = 0, format = panel->format; format; format = format->next){
  469. if (!format->use_in_gui)
  470. continue;
  471. if (i == col){
  472. sortfn *sorting_routine;
  473. sorting_routine = get_sort_fn (format->id);
  474. if (!sorting_routine)
  475. return;
  476. if (sorting_routine == panel->sort_type)
  477. panel->reverse = !panel->reverse;
  478. panel->sort_type = sorting_routine;
  479. do_re_sort (panel);
  480. return;
  481. }
  482. i++;
  483. }
  484. }
  485. /* Convenience function to load a pixmap and mask from xpm data */
  486. static void
  487. create_pixmap (char **data, GdkPixmap **pixmap, GdkBitmap **mask)
  488. {
  489. GdkImlibImage *im;
  490. im = gdk_imlib_create_image_from_xpm_data (data);
  491. gdk_imlib_render (im, im->rgb_width, im->rgb_height);
  492. *pixmap = gdk_imlib_copy_image (im);
  493. *mask = gdk_imlib_copy_mask (im);
  494. gdk_imlib_destroy_image (im);
  495. }
  496. static void
  497. panel_create_pixmaps (void)
  498. {
  499. pixmaps_ready = TRUE;
  500. create_pixmap (directory_xpm, &icon_directory_pixmap, &icon_directory_mask);
  501. create_pixmap (link_xpm, &icon_link_pixmap, &icon_link_mask);
  502. create_pixmap (dev_xpm, &icon_dev_pixmap, &icon_dev_mask);
  503. }
  504. static void
  505. panel_file_list_scrolled (GtkAdjustment *adj, WPanel *panel)
  506. {
  507. if (!GTK_IS_ADJUSTMENT (adj)) {
  508. fprintf (stderr, "file_list_is_scrolled is called and there are not enough boats!\n");
  509. exit (1);
  510. }
  511. }
  512. static void
  513. panel_configure_file_list (WPanel *panel, GtkWidget *sw, GtkWidget *file_list)
  514. {
  515. format_e *format = panel->format;
  516. GtkObject *adjustment;
  517. int i;
  518. /* Set sorting callback */
  519. gtk_signal_connect (GTK_OBJECT (file_list), "click_column",
  520. GTK_SIGNAL_FUNC (panel_file_list_column_callback), panel);
  521. /* Configure the CList */
  522. gtk_clist_set_selection_mode (GTK_CLIST (file_list), GTK_SELECTION_SINGLE);
  523. for (i = 0, format = panel->format; format; format = format->next) {
  524. GtkJustification just;
  525. if (!format->use_in_gui)
  526. continue;
  527. /* Set desired justification */
  528. if (format->just_mode == J_LEFT)
  529. just = GTK_JUSTIFY_LEFT;
  530. else
  531. just = GTK_JUSTIFY_RIGHT;
  532. gtk_clist_set_column_justification (GTK_CLIST (file_list), i, just);
  533. i++;
  534. }
  535. /* Configure the scrolbars */
  536. adjustment = GTK_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw)));
  537. gtk_signal_connect_after (adjustment, "value_changed",
  538. GTK_SIGNAL_FUNC (panel_file_list_scrolled), panel);
  539. }
  540. /*
  541. * Creates an uri list to be transfered during a drop operation.
  542. */
  543. static void *
  544. panel_build_selected_file_list (WPanel *panel, int *file_list_len)
  545. {
  546. if (panel->marked){
  547. char *sep = "\r\n";
  548. char *data, *copy;
  549. int i, total_len;
  550. int cwdlen = strlen (panel->cwd) + 1;
  551. int filelen = strlen ("file:");
  552. int seplen = strlen ("\r\n");
  553. /* first pass, compute the length */
  554. total_len = 0;
  555. for (i = 0; i < panel->count; i++)
  556. if (panel->dir.list [i].f.marked)
  557. total_len += (filelen + cwdlen + panel->dir.list [i].fnamelen + seplen);
  558. total_len++;
  559. data = copy = xmalloc (total_len, "build_selected_file_list");
  560. for (i = 0; i < panel->count; i++)
  561. if (panel->dir.list [i].f.marked){
  562. strcpy (copy, "file:");
  563. strcpy (&copy [filelen], panel->cwd);
  564. copy [filelen+cwdlen-1] = '/';
  565. strcpy (&copy [filelen + cwdlen], panel->dir.list [i].fname);
  566. strcpy (&copy [filelen + cwdlen + panel->dir.list [i].fnamelen], sep);
  567. copy += filelen + cwdlen + panel->dir.list [i].fnamelen + seplen;
  568. }
  569. data [total_len] = 0;
  570. *file_list_len = total_len;
  571. return data;
  572. } else {
  573. char *fullname, *uri;
  574. fullname = concat_dir_and_file (panel->cwd, panel->dir.list [panel->selected].fname);
  575. uri = copy_strings ("file:", fullname, NULL);
  576. free (fullname);
  577. *file_list_len = strlen (uri) + 1;
  578. return uri;
  579. }
  580. }
  581. /**
  582. * panel_drag_data_get:
  583. *
  584. * Invoked when a drag operation has been performed, this routine
  585. * provides the data to be transfered
  586. */
  587. static void
  588. panel_drag_data_get (GtkWidget *widget,
  589. GdkDragContext *context,
  590. GtkSelectionData *selection_data,
  591. guint info,
  592. guint32 time,
  593. WPanel *panel)
  594. {
  595. int len;
  596. char *data;
  597. switch (info){
  598. case TARGET_URI_LIST:
  599. case TARGET_TEXT_PLAIN:
  600. data = panel_build_selected_file_list (panel, &len);
  601. gtk_selection_data_set (
  602. selection_data, selection_data->target, 8,
  603. data, len);
  604. break;
  605. }
  606. }
  607. /**
  608. * panel_drag_data_delete:
  609. *
  610. * Invoked when the destination requests the information to be deleted
  611. * possibly because the operation was MOVE.
  612. */
  613. static void
  614. panel_drag_data_delete (GtkWidget *widget, GdkDragContext *context, WPanel *panel)
  615. {
  616. /* Things is: The File manager already handles file moving */
  617. }
  618. /**
  619. * panel_icon_list_drag_data_received:
  620. *
  621. * Invoked on the target side of a Drag and Drop operation when data has been
  622. * dropped.
  623. */
  624. static void
  625. panel_icon_list_drag_data_received (GtkWidget *widget,
  626. GdkDragContext *context,
  627. gint x,
  628. gint y,
  629. GtkSelectionData *selection_data,
  630. guint info,
  631. guint32 time,
  632. WPanel *panel)
  633. {
  634. GnomeIconList *gil = GNOME_ICON_LIST (widget);
  635. char *dir;
  636. int idx;
  637. idx = gnome_icon_list_get_icon_at (gil, x, y);
  638. if (idx == -1)
  639. dir = g_strdup (panel->cwd);
  640. else {
  641. if (panel->dir.list [idx].f.link_to_dir ||
  642. S_ISDIR (panel->dir.list [idx].buf.st_mode))
  643. dir = concat_dir_and_file (panel->cwd, panel->dir.list [idx].fname);
  644. else
  645. dir = g_strdup (panel->cwd);
  646. }
  647. gdnd_drop_on_directory (context, selection_data, dir);
  648. free (dir);
  649. update_one_panel_widget (panel, 0, UP_KEEPSEL);
  650. panel_update_contents (panel);
  651. }
  652. /**
  653. * panel_clist_drag_data_received:
  654. *
  655. * Invoked on the target side of a Drag and Drop operation when data has been
  656. * dropped.
  657. */
  658. static void
  659. panel_clist_drag_data_received (GtkWidget *widget,
  660. GdkDragContext *context,
  661. gint x,
  662. gint y,
  663. GtkSelectionData *selection_data,
  664. guint info,
  665. guint32 time,
  666. WPanel *panel)
  667. {
  668. GtkCList *clist = GTK_CLIST (widget);
  669. char *dir;
  670. int row;
  671. if (gtk_clist_get_selection_info (clist, x, y, &row, NULL) == 0)
  672. dir = g_strdup (panel->cwd);
  673. else {
  674. g_assert (row < panel->count);
  675. if (S_ISDIR (panel->dir.list [row].buf.st_mode) ||
  676. panel->dir.list [row].f.link_to_dir)
  677. dir = concat_dir_and_file (panel->cwd, panel->dir.list [row].fname);
  678. else
  679. dir = g_strdup (panel->cwd);
  680. }
  681. gdnd_drop_on_directory (context, selection_data, dir);
  682. free (dir);
  683. update_one_panel_widget (panel, 0, UP_KEEPSEL);
  684. panel_update_contents (panel);
  685. }
  686. /**
  687. * panel_tree_drag_data_received:
  688. *
  689. * Invoked on the target side when a drop has been received in the Tree
  690. */
  691. static void
  692. panel_tree_drag_data_received (GtkWidget *widget,
  693. GdkDragContext *context,
  694. gint x,
  695. gint y,
  696. GtkSelectionData *selection_data,
  697. guint info,
  698. guint32 time,
  699. WPanel *panel)
  700. {
  701. GtkDTree *dtree = GTK_DTREE (widget);
  702. GtkCTreeNode *node;
  703. int row, col;
  704. char *path;
  705. if (!gtk_clist_get_selection_info (GTK_CLIST (dtree), x, y, &row, &col))
  706. return;
  707. node = gtk_ctree_node_nth (GTK_CTREE (dtree), row);
  708. if (!node)
  709. return;
  710. gtk_ctree_expand_recursive (GTK_CTREE (dtree), node);
  711. path = gtk_dtree_get_row_path (dtree, node, 0);
  712. gdnd_drop_on_directory (context, selection_data, path);
  713. g_free (path);
  714. }
  715. static void
  716. load_dnd_icons (void)
  717. {
  718. if (!drag_directory)
  719. drag_directory = gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NOT, NULL);
  720. if (!drag_directory_ok)
  721. drag_directory_ok = gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NEW, NULL);
  722. if (!drag_multiple)
  723. drag_multiple = gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NOT, NULL);
  724. if (!drag_multiple_ok)
  725. drag_multiple_ok = gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_MULTIPLE, NULL);
  726. }
  727. static int
  728. panel_clist_button_press (GtkWidget *widget, GdkEventButton *event, WPanel *panel)
  729. {
  730. panel->maybe_start_drag = event->button;
  731. panel->click_x = event->x;
  732. panel->click_y = event->y;
  733. return FALSE;
  734. }
  735. static int
  736. panel_clist_button_release (GtkWidget *widget, GdkEventButton *event, WPanel *panel)
  737. {
  738. panel->maybe_start_drag = 0;
  739. return FALSE;
  740. }
  741. static int
  742. panel_widget_motion (GtkWidget *widget, GdkEventMotion *event, WPanel *panel)
  743. {
  744. GtkTargetList *list;
  745. GdkDragContext *context;
  746. if (!panel->maybe_start_drag)
  747. return FALSE;
  748. if (panel->maybe_start_drag == 3)
  749. return FALSE;
  750. if ((abs (event->x - panel->click_x) < 4) ||
  751. (abs (event->y - panel->click_y) < 4))
  752. return FALSE;
  753. list = gtk_target_list_new (drag_types, ELEMENTS (drag_types));
  754. context = gtk_drag_begin (widget, list,
  755. GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK,
  756. panel->maybe_start_drag, (GdkEvent *) event);
  757. gtk_drag_set_icon_default (context);
  758. return FALSE;
  759. }
  760. /**
  761. * panel_drag_begin:
  762. *
  763. * Invoked when a drag is starting in the List view or the Icon view
  764. */
  765. static void
  766. panel_drag_begin (GtkWidget *widget, GdkDragContext *context, WPanel *panel)
  767. {
  768. panel->dragging = 1;
  769. }
  770. /**
  771. * panel_drag_end:
  772. *
  773. * Invoked when a drag has finished in the List view or the Icon view
  774. */
  775. static void
  776. panel_drag_end (GtkWidget *widget, GdkDragContext *context, WPanel *panel)
  777. {
  778. panel->dragging = 0;
  779. }
  780. /*
  781. * Create, setup the file listing display.
  782. */
  783. static GtkWidget *
  784. panel_create_file_list (WPanel *panel)
  785. {
  786. const int items = panel->format->items;
  787. format_e *format = panel->format;
  788. GtkWidget *file_list;
  789. GtkWidget *sw;
  790. gchar **titles;
  791. int i;
  792. titles = g_new (char *, items);
  793. for (i = 0; i < items; format = format->next)
  794. if (format->use_in_gui)
  795. titles [i++] = format->title;
  796. sw = gtk_scrolled_window_new (NULL, NULL);
  797. gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  798. file_list = gtk_blist_new_with_titles (items, titles);
  799. gtk_container_add (GTK_CONTAINER (sw), file_list);
  800. gtk_widget_show (file_list);
  801. panel_configure_file_list (panel, sw, file_list);
  802. g_free (titles);
  803. gtk_signal_connect_after (GTK_OBJECT (sw), "size_allocate",
  804. GTK_SIGNAL_FUNC (panel_file_list_size_allocate_hook),
  805. panel);
  806. gtk_signal_connect (GTK_OBJECT (file_list), "select_row",
  807. GTK_SIGNAL_FUNC (panel_file_list_select_row),
  808. panel);
  809. /* Set up drag and drop */
  810. load_dnd_icons ();
  811. gtk_drag_dest_set (GTK_WIDGET (file_list), GTK_DEST_DEFAULT_ALL,
  812. drop_types, ELEMENTS (drop_types),
  813. GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
  814. gtk_signal_connect (GTK_OBJECT (file_list), "drag_data_get",
  815. GTK_SIGNAL_FUNC (panel_drag_data_get), panel);
  816. gtk_signal_connect (GTK_OBJECT (file_list), "drag_data_delete",
  817. GTK_SIGNAL_FUNC (panel_drag_data_delete), panel);
  818. gtk_signal_connect (GTK_OBJECT (file_list), "drag_data_received",
  819. GTK_SIGNAL_FUNC (panel_clist_drag_data_received), panel);
  820. /* These implement our drag-start activation code. We need to
  821. * manually activate the drag as the DnD code in Gtk+ will
  822. * make the scrollbars in the CList activate drags when they
  823. * are moved.
  824. */
  825. gtk_signal_connect (GTK_OBJECT (file_list), "button_press_event",
  826. GTK_SIGNAL_FUNC (panel_clist_button_press), panel);
  827. gtk_signal_connect (GTK_OBJECT (file_list), "button_release_event",
  828. GTK_SIGNAL_FUNC (panel_clist_button_release), panel);
  829. gtk_signal_connect (GTK_OBJECT (file_list), "motion_notify_event",
  830. GTK_SIGNAL_FUNC (panel_widget_motion), panel);
  831. gtk_signal_connect (GTK_OBJECT (file_list), "drag_begin",
  832. GTK_SIGNAL_FUNC (panel_drag_begin), panel);
  833. gtk_signal_connect (GTK_OBJECT (file_list), "drag_end",
  834. GTK_SIGNAL_FUNC (panel_drag_end), panel);
  835. return sw;
  836. }
  837. /*
  838. * Callback: icon selected
  839. */
  840. static void
  841. panel_icon_list_select_icon (GtkWidget *widget, int index, GdkEvent *event, WPanel *panel)
  842. {
  843. panel->selected = index;
  844. do_file_mark (panel, index, 1);
  845. display_mini_info (panel);
  846. execute_hooks (select_file_hook);
  847. if (!event)
  848. return;
  849. switch (event->type){
  850. case GDK_BUTTON_PRESS:
  851. if (event->button.button == 3) {
  852. gpopup_do_popup ((GdkEventButton *) event, panel, index, panel->dir.list[index].fname);
  853. return;
  854. }
  855. break;
  856. case GDK_2BUTTON_PRESS:
  857. if (event->button.button == 1)
  858. do_enter (panel);
  859. break;
  860. default:
  861. break;
  862. }
  863. }
  864. static void
  865. panel_icon_list_unselect_icon (GtkWidget *widget, int index, GdkEvent *event, WPanel *panel)
  866. {
  867. do_file_mark (panel, index, 0);
  868. display_mini_info (panel);
  869. if (panel->marked == 0)
  870. panel->selected = 0;
  871. }
  872. static int
  873. panel_icon_renamed (GtkWidget *widget, int index, char *dest, WPanel *panel)
  874. {
  875. char *source;
  876. source = panel->dir.list [index].fname;
  877. if (mc_rename (source, dest) == 0){
  878. free (panel->dir.list [index].fname);
  879. panel->dir.list [index].fname = strdup (dest);
  880. return TRUE;
  881. } else
  882. return FALSE;
  883. }
  884. static GdkImlibImage *
  885. load_image_icon_view (char *base)
  886. {
  887. GdkImlibImage *im;
  888. char *f = concat_dir_and_file (ICONDIR, base);
  889. im = gdk_imlib_load_image (f);
  890. g_free (f);
  891. return im;
  892. }
  893. static void
  894. load_imlib_icons (void)
  895. {
  896. static int loaded;
  897. if (loaded)
  898. return;
  899. icon_view_directory = load_image_icon_view ("i-directory.png");
  900. icon_view_executable = load_image_icon_view ("i-executable.png");
  901. icon_view_symlink = load_image_icon_view ("i-symlink.png");
  902. icon_view_device = load_image_icon_view ("i-device.png");
  903. icon_view_regular = load_image_icon_view ("i-regular.png");
  904. icon_view_core = load_image_icon_view ("i-core.png");
  905. icon_view_sock = load_image_icon_view ("i-sock.png");
  906. loaded = 1;
  907. }
  908. /*
  909. * Strategy for activaing the drags from the icon-list:
  910. *
  911. * The icon-list uses the button-press/motion-notify events for
  912. * the banding selection. We catch the events and only if the
  913. * click happens in an icon and the user moves the mouse enough (a
  914. * threshold to give it a better feel) activa the drag and drop.
  915. *
  916. */
  917. static int
  918. panel_icon_list_button_press (GtkWidget *widget, GdkEventButton *event, WPanel *panel)
  919. {
  920. GnomeIconList *gil = GNOME_ICON_LIST (widget);
  921. int icon;
  922. icon = gnome_icon_list_get_icon_at (gil, event->x, event->y);
  923. if (icon == -1)
  924. panel->maybe_start_drag = 0;
  925. else
  926. panel->maybe_start_drag = event->button;
  927. panel->click_x = event->x;
  928. panel->click_y = event->y;
  929. return FALSE;
  930. }
  931. static int
  932. panel_icon_list_button_release (GtkWidget *widget, GdkEventButton *event, WPanel *panel)
  933. {
  934. panel->maybe_start_drag = 0;
  935. return FALSE;
  936. }
  937. /* Create and setup the icon field display */
  938. static GtkWidget *
  939. panel_create_icon_display (WPanel *panel)
  940. {
  941. GnomeIconList *ilist;
  942. ilist = GNOME_ICON_LIST (gnome_icon_list_new (90, NULL, TRUE));
  943. gnome_icon_list_set_separators (ilist, " /-_.");
  944. gnome_icon_list_set_row_spacing (ilist, 2);
  945. gnome_icon_list_set_col_spacing (ilist, 2);
  946. gnome_icon_list_set_icon_border (ilist, 2);
  947. gnome_icon_list_set_text_spacing (ilist, 2);
  948. gnome_icon_list_set_selection_mode (ilist, GTK_SELECTION_MULTIPLE);
  949. GTK_WIDGET_SET_FLAGS (ilist, GTK_CAN_FOCUS);
  950. gtk_signal_connect (GTK_OBJECT (ilist), "select_icon",
  951. GTK_SIGNAL_FUNC (panel_icon_list_select_icon),
  952. panel);
  953. gtk_signal_connect (GTK_OBJECT (ilist), "unselect_icon",
  954. GTK_SIGNAL_FUNC (panel_icon_list_unselect_icon),
  955. panel);
  956. gtk_signal_connect (GTK_OBJECT (ilist), "text_changed",
  957. GTK_SIGNAL_FUNC (panel_icon_renamed),
  958. panel);
  959. /* Setup the icons and DnD */
  960. load_imlib_icons ();
  961. load_dnd_icons ();
  962. gtk_drag_dest_set (GTK_WIDGET (ilist), GTK_DEST_DEFAULT_ALL,
  963. drop_types, ELEMENTS (drop_types),
  964. GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
  965. gtk_signal_connect (GTK_OBJECT (ilist), "drag_data_get",
  966. GTK_SIGNAL_FUNC (panel_drag_data_get),
  967. panel);
  968. gtk_signal_connect (GTK_OBJECT (ilist), "drag_data_delete",
  969. GTK_SIGNAL_FUNC (panel_drag_data_delete),
  970. panel);
  971. gtk_signal_connect (GTK_OBJECT (ilist), "drag_data_received",
  972. GTK_SIGNAL_FUNC (panel_icon_list_drag_data_received),
  973. panel);
  974. gtk_signal_connect (GTK_OBJECT (ilist), "drag_begin",
  975. GTK_SIGNAL_FUNC (panel_drag_begin), panel);
  976. gtk_signal_connect (GTK_OBJECT (ilist), "drag_end",
  977. GTK_SIGNAL_FUNC (panel_drag_end), panel);
  978. /* These implement our drag-start activation code, as we have a pretty oveloaded widget */
  979. gtk_signal_connect (GTK_OBJECT (ilist), "button_press_event",
  980. GTK_SIGNAL_FUNC (panel_icon_list_button_press),
  981. panel);
  982. gtk_signal_connect (GTK_OBJECT (ilist), "button_release_event",
  983. GTK_SIGNAL_FUNC (panel_icon_list_button_release),
  984. panel);
  985. gtk_signal_connect (GTK_OBJECT (ilist), "motion_notify_event",
  986. GTK_SIGNAL_FUNC (panel_widget_motion),
  987. panel);
  988. return GTK_WIDGET (ilist);
  989. }
  990. static void
  991. panel_switch_new_display_mode (WPanel *panel)
  992. {
  993. GtkWidget *old_list = panel->list;
  994. if (!old_list)
  995. return;
  996. panel->list = panel_create_file_list (panel);
  997. gtk_widget_destroy (old_list);
  998. gtk_table_attach (GTK_TABLE (panel->view_table), panel->list, 0, 1, 0, 1,
  999. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1000. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1001. 0, 0);
  1002. gtk_widget_show (panel->list);
  1003. panel_update_contents (panel);
  1004. }
  1005. static GtkWidget *
  1006. panel_create_cwd (Dlg_head *h, WPanel *panel, void **entry)
  1007. {
  1008. WInput *in;
  1009. in = input_new (0, 0, 0, 10, "", "cwd");
  1010. add_widget (h, in);
  1011. /* Force the creation of the gtk widget */
  1012. send_message_to (h, (Widget *) in, WIDGET_INIT, 0);
  1013. *entry = in;
  1014. return GTK_WIDGET (in->widget.wdata);
  1015. }
  1016. /* FIXME: for now, this list is hardcoded. We want a way to let the user configure it. */
  1017. static struct filter_item {
  1018. char *text;
  1019. char *glob;
  1020. } filter_items [] = {
  1021. { N_("All files"),
  1022. "*" },
  1023. { N_("Archives and compressed files"),
  1024. "*.(tar|gz|tgz|taz|zip|lha|zoo|pak|sit|arc|arj|rar|huf|lzh)" },
  1025. { N_("RPM/DEB files"),
  1026. "*.(rpm|deb)" },
  1027. { N_("Text/Document files"),
  1028. "*.(txt|tex|doc|rtf)" },
  1029. { N_("HTML and SGML files"),
  1030. "*.(html|htm|sgml|sgm)" },
  1031. { N_("Postscript and PDF files"),
  1032. "*.(ps|pdf)" },
  1033. { N_("Spreadsheet files"),
  1034. "*.(xls|wks|wk1)" },
  1035. { N_("Image files"),
  1036. "*.(png|jpg|jpeg|xcf|gif|tif|tiff|xbm|xpm|pbm|pgm|ppm|tga|rgb|iff|lbm|ilbm|"
  1037. "bmp|pcx|pic|pict|psd|gbr|pat|ico|fig|cgm|rle|fits)" },
  1038. { N_("Video/animation files"),
  1039. "*.(mpg|mpeg|mov|avi|fli|flc|flh|flx|dl)" },
  1040. { N_("Audio files"),
  1041. "*.(au|wav|mp3|snd|mod|s3m|ra)" },
  1042. { N_("C program files"),
  1043. "*.[ch]" },
  1044. { N_("C++ program files"),
  1045. "*.(cc|C|cpp|cxx|h|H)" },
  1046. { N_("Objective-C program files"),
  1047. "*.[mh]" },
  1048. { N_("Scheme program files"),
  1049. "*.scm" },
  1050. { N_("Assembler program files"),
  1051. "*.(s|S|asm)" },
  1052. { N_("Misc. program files"),
  1053. "*.(awk|sed|lex|l|y|sh|idl|pl|py|am|in|f|el|bas|pas|java|sl|p|m4|tcl|pov)" },
  1054. { N_("Font files"),
  1055. "*.(pfa|pfb|afm|ttf|fon|pcf|pcf.gz|spd)" }
  1056. };
  1057. static GtkWidget *filter_menu;
  1058. static void
  1059. filter_item_select (GtkWidget *widget, gpointer data)
  1060. {
  1061. /* FIXME: the hintbar resizes horribly and screws the panel */
  1062. #if 0
  1063. struct filter_item *fi = gtk_object_get_user_data (GTK_OBJECT (widget));
  1064. set_hintbar (easy_patterns ? fi->glob : fi->regexp);
  1065. #endif
  1066. }
  1067. static void
  1068. filter_item_deselect (GtkWidget *widget, gpointer data)
  1069. {
  1070. /* set_hintbar (""); */
  1071. }
  1072. static void
  1073. filter_item_activate (GtkWidget *widget, gpointer data)
  1074. {
  1075. struct filter_item *fi = gtk_object_get_user_data (GTK_OBJECT (widget));
  1076. WPanel *panel = data;
  1077. char *pattern;
  1078. if (easy_patterns)
  1079. pattern = g_strdup (fi->glob);
  1080. else {
  1081. /* This is sort of a hack to force convert_pattern() to actually convert the thing */
  1082. easy_patterns = 1;
  1083. pattern = convert_pattern (fi->glob, match_file, 0);
  1084. easy_patterns = 0;
  1085. }
  1086. set_panel_filter_to (panel, pattern);
  1087. }
  1088. static void
  1089. build_filter_menu (WPanel *panel, GtkWidget *button)
  1090. {
  1091. GtkWidget *item;
  1092. int i;
  1093. if (filter_menu)
  1094. return;
  1095. /* FIXME: the filter menu is global, and it is never destroyed */
  1096. filter_menu = gtk_menu_new ();
  1097. gtk_object_set_user_data (GTK_OBJECT (filter_menu), button);
  1098. for (i = 0; i < ELEMENTS (filter_items); i++) {
  1099. item = gtk_menu_item_new_with_label (_(filter_items[i].text));
  1100. gtk_object_set_user_data (GTK_OBJECT (item), &filter_items[i]);
  1101. gtk_signal_connect (GTK_OBJECT (item), "select",
  1102. (GtkSignalFunc) filter_item_select,
  1103. panel);
  1104. gtk_signal_connect (GTK_OBJECT (item), "deselect",
  1105. (GtkSignalFunc) filter_item_deselect,
  1106. panel);
  1107. gtk_signal_connect (GTK_OBJECT (item), "activate",
  1108. (GtkSignalFunc) filter_item_activate,
  1109. panel);
  1110. gtk_widget_show (item);
  1111. gtk_menu_append (GTK_MENU (filter_menu), item);
  1112. }
  1113. }
  1114. static void
  1115. position_filter_popup (GtkMenu *menu, gint *x, gint *y, gpointer data)
  1116. {
  1117. int screen_width, screen_height;
  1118. GtkWidget *wmenu = GTK_WIDGET (menu);
  1119. GtkWidget *button = GTK_WIDGET (data);
  1120. /* This code is mostly ripped off from gtkmenu.c - Federico */
  1121. screen_width = gdk_screen_width ();
  1122. screen_height = gdk_screen_height ();
  1123. gdk_window_get_origin (button->window, x, y);
  1124. *y += button->allocation.height;
  1125. if ((*x + wmenu->requisition.width) > screen_width)
  1126. *x -= (*x + wmenu->requisition.width) - screen_width;
  1127. if ((*y + wmenu->requisition.height) > screen_height)
  1128. *y -= (*y + wmenu->requisition.height) - screen_height;
  1129. if (*y < 0)
  1130. *y = 0;
  1131. }
  1132. static void
  1133. show_filter_popup (GtkWidget *button, gpointer data)
  1134. {
  1135. WPanel *panel;
  1136. panel = data;
  1137. build_filter_menu (panel, button);
  1138. gtk_menu_popup (GTK_MENU (filter_menu), NULL, NULL,
  1139. position_filter_popup,
  1140. button,
  1141. 1,
  1142. GDK_CURRENT_TIME);
  1143. }
  1144. void
  1145. display_mini_info (WPanel *panel)
  1146. {
  1147. GtkLabel *label = GTK_LABEL (panel->ministatus);
  1148. if (panel->searching) {
  1149. char *buf;
  1150. buf = g_strdup_printf (_("Search: %s"), panel->search_buffer);
  1151. gtk_label_set (label, buf);
  1152. g_free (buf);
  1153. return;
  1154. }
  1155. if (panel->marked){
  1156. char *buf;
  1157. buf = g_strdup_printf ((panel->marked == 1) ? _("%s bytes in %d file") : _("%s bytes in %d files"),
  1158. size_trunc_sep (panel->total),
  1159. panel->marked);
  1160. gtk_label_set (label, buf);
  1161. g_free (buf);
  1162. return;
  1163. }
  1164. if (S_ISLNK (panel->dir.list [panel->selected].buf.st_mode)){
  1165. char *link, link_target [MC_MAXPATHLEN];
  1166. int len;
  1167. link = concat_dir_and_file (panel->cwd, panel->dir.list [panel->selected].fname);
  1168. len = mc_readlink (link, link_target, MC_MAXPATHLEN);
  1169. free (link);
  1170. if (len > 0){
  1171. char *str;
  1172. link_target [len] = 0;
  1173. str = copy_strings ("-> ", link_target, NULL);
  1174. gtk_label_set (label, str);
  1175. free (str);
  1176. } else
  1177. gtk_label_set (label, _("<readlink failed>"));
  1178. return;
  1179. }
  1180. if (panel->estimated_total){
  1181. int len = panel->estimated_total;
  1182. char *buffer;
  1183. buffer = xmalloc (len + 2, "display_mini_info");
  1184. format_file (buffer, panel, panel->selected, panel->estimated_total-2, 0, 1);
  1185. buffer [len] = 0;
  1186. gtk_label_set (label, buffer);
  1187. free (buffer);
  1188. }
  1189. if (panel->list_type == list_icons){
  1190. if (panel->marked == 0){
  1191. gtk_label_set (label, "");
  1192. }
  1193. }
  1194. }
  1195. static GtkWidget *
  1196. panel_create_filter (Dlg_head *h, WPanel *panel, void **filter_w)
  1197. {
  1198. GtkWidget *fhbox;
  1199. GtkWidget *button;
  1200. GtkWidget *arrow;
  1201. GtkWidget *label;
  1202. GtkWidget *ihbox;
  1203. WInput *in;
  1204. fhbox = gtk_hbox_new (FALSE, 0);
  1205. /* Filter popup button */
  1206. button = gtk_button_new ();
  1207. gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1208. (GtkSignalFunc) show_filter_popup,
  1209. panel);
  1210. GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
  1211. gtk_box_pack_start (GTK_BOX (fhbox), button, FALSE, FALSE, 0);
  1212. gtk_widget_show (button);
  1213. ihbox = gtk_hbox_new (FALSE, 3);
  1214. gtk_container_add (GTK_CONTAINER (button), ihbox);
  1215. gtk_widget_show (ihbox);
  1216. arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
  1217. gtk_box_pack_start (GTK_BOX (ihbox), arrow, TRUE, TRUE, 0);
  1218. gtk_widget_show (arrow);
  1219. label = gtk_label_new (_("Filter"));
  1220. gtk_box_pack_start (GTK_BOX (ihbox), label, TRUE, TRUE, 0);
  1221. gtk_widget_show (label);
  1222. /* Filter input line */
  1223. in = input_new (0, 0, 0, 10, "", "filter");
  1224. add_widget (h, in);
  1225. /* Force the creation of the gtk widget */
  1226. send_message_to (h, (Widget *) in, WIDGET_INIT, 0);
  1227. *filter_w = in;
  1228. gtk_box_pack_start (GTK_BOX (fhbox), GTK_WIDGET (in->widget.wdata), TRUE, TRUE, 0);
  1229. return fhbox;
  1230. }
  1231. /* Signal handler for DTree's "directory_changed" signal */
  1232. static void
  1233. panel_chdir (GtkDTree *dtree, char *path, WPanel *panel)
  1234. {
  1235. if (!panel->dragging)
  1236. do_panel_cd (panel, path, cd_exact);
  1237. }
  1238. /**
  1239. * tree_drag_open_directory:
  1240. *
  1241. * This routine is invoked in a delayed fashion if the user
  1242. * keeps the drag cursor still over the widget.
  1243. */
  1244. static gint
  1245. tree_drag_open_directory (gpointer data)
  1246. {
  1247. WPanel *panel = data;
  1248. GtkCTreeNode *node;
  1249. int row, col;
  1250. int r;
  1251. r = gtk_clist_get_selection_info (
  1252. GTK_CLIST (panel->tree),
  1253. GTK_DTREE (panel->tree)->drag_motion_x,
  1254. GTK_DTREE (panel->tree)->drag_motion_y,
  1255. &row, &col);
  1256. if (!r)
  1257. return FALSE;
  1258. node = gtk_ctree_node_nth (GTK_CTREE (panel->tree), row);
  1259. if (!node)
  1260. return FALSE;
  1261. gtk_ctree_expand_recursive (GTK_CTREE (panel->tree), node);
  1262. return FALSE;
  1263. }
  1264. static GtkAdjustment *
  1265. scrolled_window_get_vadjustment (GtkScrolledWindow *sw)
  1266. {
  1267. GtkRange *vsb = GTK_RANGE (sw->vscrollbar);
  1268. GtkAdjustment *va = vsb->adjustment;
  1269. return va;
  1270. }
  1271. /**
  1272. * panel_tree_scrolling_is_desirable:
  1273. *
  1274. * If the cursor is in a position close to either edge (top or bottom)
  1275. * and there is possible to scroll the window, this routine returns
  1276. * true.
  1277. */
  1278. static gboolean
  1279. panel_tree_scrolling_is_desirable (WPanel *panel, int x, int y)
  1280. {
  1281. GtkDTree *dtree = GTK_DTREE (panel->tree);
  1282. GtkAdjustment *va;
  1283. va = scrolled_window_get_vadjustment (panel->tree_scrolled_window);
  1284. if (y < 10){
  1285. if (va->value > va->lower)
  1286. return TRUE;
  1287. } else {
  1288. if (y > (GTK_WIDGET (dtree)->allocation.height-20)){
  1289. if (va->value < va->upper)
  1290. return TRUE;
  1291. }
  1292. }
  1293. return FALSE;
  1294. }
  1295. /**
  1296. * panel_tree_scroll:
  1297. *
  1298. * Timer callback invoked to scroll the tree window
  1299. */
  1300. static gboolean
  1301. panel_tree_scroll (gpointer data)
  1302. {
  1303. WPanel *panel = data;
  1304. GtkAdjustment *va;
  1305. va = scrolled_window_get_vadjustment (panel->tree_scrolled_window);
  1306. if (GTK_DTREE (panel->tree)->drag_motion_y < 10)
  1307. gtk_adjustment_set_value (va, va->value - va->step_increment);
  1308. else{
  1309. gtk_adjustment_set_value (va, va->value + va->step_increment);
  1310. }
  1311. return FALSE;
  1312. }
  1313. /**
  1314. * panel_tree_drag_motion:
  1315. *
  1316. * This routine is invoked by GTK+ when an item is being dragged on
  1317. * top of our widget. We setup a timed function that will open the
  1318. * Tree node
  1319. */
  1320. static gboolean
  1321. panel_tree_drag_motion (GtkWidget *widget, GdkDragContext *ctx, int x, int y, guint time, void *data)
  1322. {
  1323. GtkDTree *dtree = GTK_DTREE (widget);
  1324. WPanel *panel = data;
  1325. int r, row, col;
  1326. if (dtree->timer_id != -1){
  1327. gtk_timeout_remove (dtree->timer_id);
  1328. dtree->timer_id = -1;
  1329. }
  1330. dtree->drag_motion_x = x;
  1331. dtree->drag_motion_y = y;
  1332. if (panel_tree_scrolling_is_desirable (panel, x, y)){
  1333. dtree->timer_id = gtk_timeout_add (60, panel_tree_scroll, data);
  1334. return TRUE;
  1335. }
  1336. r = gtk_clist_get_selection_info (
  1337. GTK_CLIST (widget), x, y, &row, &col);
  1338. dtree->timer_id = gtk_timeout_add (200, tree_drag_open_directory, data);
  1339. return TRUE;
  1340. }
  1341. /**
  1342. * panel_tree_drag_leave:
  1343. *
  1344. * Invoked by GTK+ when the dragging cursor has abandoned our widget.
  1345. * We kill any pending timers.
  1346. */
  1347. static void
  1348. panel_tree_drag_leave (GtkWidget *widget, GdkDragContext *ctx, int x, int y, guint time, void *data)
  1349. {
  1350. GtkDTree *dtree = GTK_DTREE (widget);
  1351. printf ("Got drag_leave\n");
  1352. if (dtree->timer_id == -1){
  1353. gtk_timeout_remove (dtree->timer_id);
  1354. dtree->timer_id = -1;
  1355. }
  1356. }
  1357. /**
  1358. * panel_tree_drag_begin:
  1359. *
  1360. * callback invoked when the drag action starts from the Tree
  1361. */
  1362. static void
  1363. panel_tree_drag_begin (GtkWidget *widget, GdkDragContext *context, WPanel *panel)
  1364. {
  1365. GtkDTree *dtree = GTK_DTREE (widget);
  1366. panel->dragging = 1;
  1367. dtree->drag_dir = g_strdup (dtree->current_path);
  1368. printf ("This is the directory being dragged: %s\n", dtree->current_path);
  1369. }
  1370. /**
  1371. * panel_tree_drag_end:
  1372. *
  1373. * callback invoked when the drag action initiated by the tree finishes.
  1374. */
  1375. static void
  1376. panel_tree_drag_end (GtkWidget *widget, GdkDragContext *context, WPanel *panel)
  1377. {
  1378. GtkDTree *dtree = GTK_DTREE (widget);
  1379. panel->dragging = 0;
  1380. g_free (dtree->current_path);
  1381. dtree->current_path = NULL;
  1382. }
  1383. /**
  1384. * panel_tree_drag_data_get:
  1385. *
  1386. * Invoked when the tree is required to provide the dragged data
  1387. */
  1388. static void
  1389. panel_tree_drag_data_get (GtkWidget *widget, GdkDragContext *context,
  1390. GtkSelectionData *selection_data, guint info,
  1391. guint32 time)
  1392. {
  1393. GtkDTree *dtree = GTK_DTREE (widget);
  1394. char *data;
  1395. printf ("TREE DATA GET\n");
  1396. switch (info){
  1397. case TARGET_URI_LIST:
  1398. case TARGET_TEXT_PLAIN:
  1399. data = copy_strings ("file:", dtree->drag_dir, NULL);
  1400. gtk_selection_data_set (
  1401. selection_data, selection_data->target, 8,
  1402. data, strlen (data)+1);
  1403. break;
  1404. }
  1405. }
  1406. /**
  1407. * panel_create_tree_view:
  1408. *
  1409. * Create and initializes the GtkDTree widget for being used in the
  1410. * Panel
  1411. */
  1412. static GtkWidget *
  1413. panel_create_tree_view (WPanel *panel)
  1414. {
  1415. GtkWidget *tree;
  1416. tree = gtk_dtree_new ();
  1417. gtk_signal_connect (GTK_OBJECT (tree), "directory_changed",
  1418. GTK_SIGNAL_FUNC (panel_chdir), panel);
  1419. gtk_drag_dest_set (GTK_WIDGET (tree), GTK_DEST_DEFAULT_ALL,
  1420. drop_types, ELEMENTS (drop_types),
  1421. GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
  1422. /*
  1423. * Drag and drop signals.
  1424. */
  1425. /* Data has been dropped signal handler */
  1426. gtk_signal_connect (GTK_OBJECT (tree), "drag_data_received",
  1427. GTK_SIGNAL_FUNC (panel_tree_drag_data_received), panel);
  1428. gtk_signal_connect (GTK_OBJECT (tree), "drag_begin",
  1429. GTK_SIGNAL_FUNC (panel_tree_drag_begin), panel);
  1430. gtk_signal_connect (GTK_OBJECT (tree), "drag_end",
  1431. GTK_SIGNAL_FUNC (panel_tree_drag_end), panel);
  1432. gtk_signal_connect (GTK_OBJECT (tree), "drag_data_get",
  1433. GTK_SIGNAL_FUNC (panel_tree_drag_data_get), panel);
  1434. /* Make directories draggable */
  1435. gtk_drag_source_set (GTK_WIDGET (tree), GDK_BUTTON1_MASK,
  1436. drag_types, ELEMENTS (drag_types),
  1437. GDK_ACTION_LINK | GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_ASK);
  1438. /* Mouse is being moved over ourselves */
  1439. gtk_signal_connect (GTK_OBJECT (tree), "drag_motion",
  1440. GTK_SIGNAL_FUNC (panel_tree_drag_motion), panel);
  1441. gtk_signal_connect (GTK_OBJECT (tree), "drag_leave",
  1442. GTK_SIGNAL_FUNC (panel_tree_drag_leave), panel);
  1443. return tree;
  1444. }
  1445. /*
  1446. * create_and_setup_pane:
  1447. *
  1448. * Creates the horizontal GtkPaned widget that holds the tree
  1449. * and the listing/iconing displays
  1450. */
  1451. static GtkWidget *
  1452. create_and_setup_pane (WPanel *panel)
  1453. {
  1454. GtkWidget *pane;
  1455. GtkWidget *tree = panel->tree;
  1456. GdkFont *tree_font = tree->style->font;
  1457. pane = gtk_hpaned_new ();
  1458. /*
  1459. * Hack: set the default startup size for the pane without
  1460. * using _set_usize which would set the minimal size
  1461. */
  1462. GTK_PANED (pane)->child1_size = 20 * gdk_string_width (tree_font, "W");
  1463. GTK_PANED (pane)->position_set = TRUE;
  1464. gtk_widget_show (pane);
  1465. return pane;
  1466. }
  1467. static void
  1468. panel_back (GtkWidget *button, WPanel *panel)
  1469. {
  1470. directory_history_prev (panel);
  1471. }
  1472. static void
  1473. panel_fwd (GtkWidget *button, WPanel *panel)
  1474. {
  1475. directory_history_next (panel);
  1476. }
  1477. static void
  1478. panel_up (GtkWidget *button, WPanel *panel)
  1479. {
  1480. do_panel_cd (panel, "..", cd_exact);
  1481. }
  1482. static GtkWidget *
  1483. button_switch_to (char **icon, GtkSignalFunc fn, void *closure)
  1484. {
  1485. GtkWidget *button, *pix;
  1486. button = gtk_button_new ();
  1487. pix = gnome_pixmap_new_from_xpm_d (icon);
  1488. gtk_container_add (GTK_CONTAINER (button), pix);
  1489. gtk_signal_connect (GTK_OBJECT (button), "clicked", fn, closure);
  1490. return button;
  1491. }
  1492. static void
  1493. do_switch_to_iconic (GtkWidget *widget, WPanel *panel)
  1494. {
  1495. if (panel->list_type == list_icons)
  1496. return;
  1497. panel->list_type = list_icons;
  1498. set_panel_formats (panel);
  1499. paint_panel (panel);
  1500. do_refresh ();
  1501. }
  1502. static void
  1503. do_switch_to_listing (GtkWidget *widget, WPanel *panel)
  1504. {
  1505. if (panel->list_type != list_icons)
  1506. return;
  1507. panel->list_type = list_full;
  1508. set_panel_formats (panel);
  1509. paint_panel (panel);
  1510. do_refresh ();
  1511. }
  1512. static GtkWidget *
  1513. button_switch_to_icon (WPanel *panel)
  1514. {
  1515. return button_switch_to (listing_iconic_xpm, GTK_SIGNAL_FUNC (do_switch_to_iconic), panel);
  1516. }
  1517. static GtkWidget *
  1518. button_switch_to_listing (WPanel *panel)
  1519. {
  1520. return button_switch_to (listing_list_xpm, GTK_SIGNAL_FUNC (do_switch_to_listing), panel);
  1521. }
  1522. void
  1523. x_create_panel (Dlg_head *h, widget_data parent, WPanel *panel)
  1524. {
  1525. GtkWidget *status_line, *filter, *vbox, *ministatus_box;
  1526. GtkWidget *frame, *cwd, *back_p, *fwd_p;
  1527. GtkWidget *display, *table_frame;
  1528. panel->xwindow = gtk_widget_get_toplevel (GTK_WIDGET (panel->widget.wdata));
  1529. panel->table = gtk_table_new (2, 1, 0);
  1530. /*
  1531. * Tree View
  1532. */
  1533. panel->tree_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  1534. gtk_scrolled_window_set_policy (
  1535. GTK_SCROLLED_WINDOW (panel->tree_scrolled_window),
  1536. GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  1537. panel->tree = panel_create_tree_view (panel);
  1538. gtk_container_add (GTK_CONTAINER (panel->tree_scrolled_window), panel->tree);
  1539. gtk_widget_show_all (panel->tree_scrolled_window);
  1540. /*
  1541. * Icon and Listing display
  1542. */
  1543. panel->icons = panel_create_icon_display (panel);
  1544. panel->scrollbar = gtk_vscrollbar_new (GNOME_ICON_LIST (panel->icons)->adj);
  1545. gtk_widget_show (panel->scrollbar);
  1546. panel->list = panel_create_file_list (panel);
  1547. gtk_widget_ref (panel->icons);
  1548. gtk_widget_ref (panel->list);
  1549. if (panel->list_type == list_icons)
  1550. display = panel->icons;
  1551. else
  1552. display = panel->list;
  1553. /*
  1554. * Pane
  1555. */
  1556. panel->pane = create_and_setup_pane (panel);
  1557. gtk_paned_add1 (GTK_PANED (panel->pane), panel->tree_scrolled_window);
  1558. /*
  1559. * Filter
  1560. */
  1561. filter = panel_create_filter (h, panel, &panel->filter_w);
  1562. /*
  1563. * Current Working directory
  1564. */
  1565. cwd = panel_create_cwd (h, panel, &panel->current_dir);
  1566. /* We do not want the focus by default (and the previos add_widget just gave it to us) */
  1567. h->current = h->current->prev;
  1568. /*
  1569. * History buttons, and updir.
  1570. */
  1571. back_p = gnome_stock_pixmap_widget_new (panel->xwindow, GNOME_STOCK_MENU_BACK);
  1572. fwd_p = gnome_stock_pixmap_widget_new (panel->xwindow, GNOME_STOCK_MENU_FORWARD);
  1573. panel->up_b = gtk_button_new_with_label (_("Up"));
  1574. panel->back_b = gtk_button_new ();
  1575. panel->fwd_b = gtk_button_new ();
  1576. gtk_container_add (GTK_CONTAINER (panel->back_b), back_p);
  1577. gtk_container_add (GTK_CONTAINER (panel->fwd_b), fwd_p);
  1578. gtk_signal_connect (GTK_OBJECT (panel->back_b), "clicked", GTK_SIGNAL_FUNC(panel_back), panel);
  1579. gtk_signal_connect (GTK_OBJECT (panel->fwd_b), "clicked", GTK_SIGNAL_FUNC(panel_fwd), panel);
  1580. gtk_signal_connect (GTK_OBJECT (panel->up_b), "clicked", GTK_SIGNAL_FUNC(panel_up), panel);
  1581. panel_update_marks (panel);
  1582. /*
  1583. * ministatus
  1584. */
  1585. panel->ministatus = gtk_label_new (""); /* was a cliplabel */
  1586. gtk_widget_set_usize (panel->ministatus, 0, -1);
  1587. gtk_misc_set_alignment (GTK_MISC (panel->ministatus), 0.0, 0.0);
  1588. gtk_misc_set_padding (GTK_MISC (panel->ministatus), 3, 0);
  1589. gtk_widget_show (panel->ministatus);
  1590. /*
  1591. * Status line and packing of all of the toys
  1592. */
  1593. status_line = gtk_hbox_new (0, 0);
  1594. gtk_container_set_border_width (GTK_CONTAINER (status_line), 3);
  1595. gtk_label_set_justify (GTK_LABEL (panel->ministatus), GTK_JUSTIFY_LEFT);
  1596. gtk_box_pack_start (GTK_BOX (status_line), panel->back_b, 0, 0, 2);
  1597. gtk_box_pack_start (GTK_BOX (status_line), panel->up_b, 0, 0, 2);
  1598. gtk_box_pack_start (GTK_BOX (status_line), panel->fwd_b, 0, 0, 2);
  1599. gtk_box_pack_start (GTK_BOX (status_line), cwd, 1, 1, 5);
  1600. gtk_box_pack_start (GTK_BOX (status_line), button_switch_to_icon (panel), 0, 0, 2);
  1601. gtk_box_pack_start (GTK_BOX (status_line), button_switch_to_listing (panel), 0, 0, 2);
  1602. #if 0
  1603. /* Remove the filter for now, until I add another toolbar */
  1604. gtk_box_pack_end (GTK_BOX (status_line), filter, 0, 0, 0);
  1605. #endif
  1606. gtk_widget_show_all (status_line);
  1607. /*
  1608. * The statusbar
  1609. */
  1610. frame = gtk_frame_new (NULL);
  1611. gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  1612. gtk_container_set_border_width (GTK_CONTAINER (frame), 3);
  1613. panel->status = gtk_label_new (""); /* used to be a cliplabel */
  1614. gtk_misc_set_alignment (GTK_MISC (panel->status), 0.0, 0.5);
  1615. gtk_misc_set_padding (GTK_MISC (panel->status), 3, 0);
  1616. gtk_container_add (GTK_CONTAINER (frame), panel->status);
  1617. gtk_label_set_justify (GTK_LABEL (panel->status), GTK_JUSTIFY_LEFT);
  1618. gtk_widget_show_all (frame);
  1619. panel->view_table = gtk_table_new (1, 1, 0);
  1620. gtk_widget_show (panel->view_table);
  1621. /*
  1622. * Put the icon list and the file listing in a nice frame
  1623. */
  1624. table_frame = gtk_frame_new (NULL);
  1625. gtk_frame_set_shadow_type (GTK_FRAME (table_frame), GTK_SHADOW_IN);
  1626. gtk_widget_show (table_frame);
  1627. gtk_container_add (GTK_CONTAINER (table_frame), panel->view_table);
  1628. /* Add both the icon view and the listing view */
  1629. gtk_table_attach (GTK_TABLE (panel->view_table), panel->icons, 0, 1, 0, 1,
  1630. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1631. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1632. 0, 0);
  1633. gtk_table_attach (GTK_TABLE (panel->view_table), panel->scrollbar, 1, 2, 0, 1,
  1634. 0,
  1635. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1636. 0, 0);
  1637. gtk_table_attach (GTK_TABLE (panel->view_table), panel->list, 0, 1, 0, 1,
  1638. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1639. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1640. 0, 0);
  1641. gtk_widget_show (display);
  1642. gtk_table_attach (GTK_TABLE (panel->table), panel->pane, 0, 1, 1, 2,
  1643. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1644. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1645. 0, 0);
  1646. gtk_paned_add2 (GTK_PANED (panel->pane), table_frame);
  1647. gtk_table_attach (GTK_TABLE (panel->table), status_line, 0, 1, 0, 1,
  1648. GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
  1649. /*
  1650. * ministatus_box is a container created just to put the
  1651. * panel->ministatus inside.
  1652. *
  1653. * Then the resize mode for ministatus_box is changed to stop
  1654. * any size-changed messages to be propagated above.
  1655. *
  1656. * This is required as the panel->ministatus Label is changed
  1657. * very often (to display status information). If this hack
  1658. * is not made, then the resize is queued and the whole window
  1659. * flickers each time this changes
  1660. */
  1661. ministatus_box = gtk_hbox_new (FALSE, 0);
  1662. gtk_container_add (GTK_CONTAINER (ministatus_box), panel->ministatus);
  1663. gtk_widget_show (ministatus_box);
  1664. gtk_container_set_resize_mode (GTK_CONTAINER (ministatus_box), GTK_RESIZE_QUEUE);
  1665. gtk_table_attach (GTK_TABLE (panel->table), ministatus_box, 0, 1, 2, 3,
  1666. GTK_EXPAND | GTK_FILL | GTK_SHRINK,
  1667. 0, 0, 0);
  1668. gtk_table_attach (GTK_TABLE (panel->table), frame, 0, 1, 3, 4,
  1669. GTK_EXPAND | GTK_FILL,
  1670. 0, 0, 0);
  1671. /* Ultra nasty hack: pull the vbox from wdata */
  1672. vbox = GTK_WIDGET (panel->widget.wdata);
  1673. panel->widget.wdata = (widget_data) panel->table;
  1674. /* Now, insert our table in our parent */
  1675. gtk_container_add (GTK_CONTAINER (vbox), panel->table);
  1676. gtk_widget_show (vbox);
  1677. gtk_widget_show (panel->table);
  1678. if (!(panel->widget.options & W_PANEL_HIDDEN))
  1679. gtk_widget_show (gtk_widget_get_toplevel (panel->table));
  1680. if (!pixmaps_ready)
  1681. panel_create_pixmaps ();
  1682. /* In GNOME the panel wants to have the cursor, to avoid "auto" focusing the
  1683. * filter input line
  1684. */
  1685. panel->widget.options |= W_WANT_CURSOR;
  1686. panel->estimated_total = 0;
  1687. }
  1688. void
  1689. panel_update_cols (Widget *panel, int frame_size)
  1690. {
  1691. panel->cols = 60;
  1692. panel->lines = 20;
  1693. }
  1694. char *
  1695. get_nth_panel_name (int num)
  1696. {
  1697. static char buffer [20];
  1698. if (!num)
  1699. return "New Left Panel";
  1700. else if (num == 1)
  1701. return "New Right Panel";
  1702. else {
  1703. sprintf (buffer, "%ith Panel", num);
  1704. return buffer;
  1705. }
  1706. }
  1707. void
  1708. load_hint (void)
  1709. {
  1710. char *hint;
  1711. if ((hint = get_random_hint ())){
  1712. if (*hint)
  1713. set_hintbar (hint);
  1714. free (hint);
  1715. } else
  1716. set_hintbar ("The GNOME File Manager " VERSION);
  1717. }
  1718. void
  1719. paint_frame (WPanel *panel)
  1720. {
  1721. }
  1722. void
  1723. x_reset_sort_labels (WPanel *panel)
  1724. {
  1725. if (panel->list_type == list_icons){
  1726. if (panel->icons){
  1727. gtk_widget_show (panel->icons);
  1728. gtk_widget_show (panel->scrollbar);
  1729. }
  1730. if (panel->list)
  1731. gtk_widget_hide (panel->list);
  1732. } else {
  1733. panel_switch_new_display_mode (panel);
  1734. if (panel->list){
  1735. gtk_widget_show (panel->list);
  1736. gtk_widget_show (panel->scrollbar);
  1737. }
  1738. if (panel->icons){
  1739. gtk_widget_hide (panel->icons);
  1740. gtk_widget_hide (panel->scrollbar);
  1741. }
  1742. }
  1743. }
  1744. /* Releases all of the X resources allocated */
  1745. void
  1746. x_panel_destroy (WPanel *panel)
  1747. {
  1748. gtk_widget_destroy (GTK_WIDGET (panel->xwindow));
  1749. }