View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2002-2019, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9    All rights reserved.
   10
   11    Redistribution and use in source and binary forms, with or without
   12    modification, are permitted provided that the following conditions
   13    are met:
   14
   15    1. Redistributions of source code must retain the above copyright
   16       notice, this list of conditions and the following disclaimer.
   17
   18    2. Redistributions in binary form must reproduce the above copyright
   19       notice, this list of conditions and the following disclaimer in
   20       the documentation and/or other materials provided with the
   21       distribution.
   22
   23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   24    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   26    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   27    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   28    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   29    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   30    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   31    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34    POSSIBILITY OF SUCH DAMAGE.
   35*/
   36
   37:- module(win_menu,
   38          [ init_win_menus/0
   39          ]).   40:- use_module(library(lists)).   41:- use_module(library(apply)).   42:- use_module(library(error)).   43:- set_prolog_flag(generate_debug_info, false).   44:- op(200, fy, @).   45:- op(990, xfx, :=).

Console window menu

This library sets up the menu of swipl-win.exe. It is called from the system initialisation file plwin-win.rc, predicate gui_setup_/0. */

   53:- if(current_prolog_flag(console_menu_version, qt)).   54% The traditional swipl-win.exe predefines some menus.  The Qt version
   55% does not.  Here, we predefine the same menus to make the remainder
   56% compatiple.
   57menu('&File',
   58     [ 'E&xit' = pqConsole:quit_console
   59     ],
   60     [
   61     ]).
   62menu('&Edit',
   63     [ '&Copy'  = pqConsole:copy,
   64       '&Paste' = pqConsole:paste
   65     ],
   66     []).
   67menu('&Settings',
   68     [ '&Font ...' = pqConsole:select_font,
   69       '&Colors ...' = pqConsole:select_ANSI_term_colors
   70     ],
   71     []).
   72menu('&Run',
   73     [ '&Interrupt' = interrupt,
   74       '&New thread' = interactor
   75     ],
   76     []).
   77
   78menu(File,
   79     [ '&Consult ...' = action(user:load_files(+file(open,
   80                                                     'Load file into Prolog'),
   81                                               [silent(false)])),
   82       '&Edit ...'    = action(user:edit(+file(open,
   83                                               'Edit existing file'))),
   84       '&New ...'     = action(edit_new(+file(save,
   85                                              'Create new Prolog source'))),
   86       --
   87     | MRU
   88     ], [before_item('E&xit')]) :-
   89    File = '&File',
   90    findall(Mru=true, mru_info(File, Mru, _, _, _), MRU, MRUTail),
   91    MRUTail = [ --,
   92                '&Reload modified files' = user:make,
   93                --,
   94                '&Navigator ...' = prolog_ide(open_navigator),
   95                --
   96              ].
   97
   98:- else.   99
  100menu('&File',
  101     [ '&Consult ...' = action(user:load_files(+file(open,
  102                                                     'Load file into Prolog'),
  103                                               [silent(false)])),
  104       '&Edit ...'    = action(user:edit(+file(open,
  105                                               'Edit existing file'))),
  106       '&New ...'     = action(edit_new(+file(save,
  107                                              'Create new Prolog source'))),
  108       --,
  109       '&Reload modified files' = user:make,
  110       --,
  111       '&Navigator ...' = prolog_ide(open_navigator),
  112       --
  113     ],
  114     [ before_item('&Exit')
  115     ]).
  116:- endif.  117
  118menu('&Settings',
  119     [ --,
  120       '&User init file ...'  = prolog_edit_preferences(prolog),
  121       '&GUI preferences ...' = prolog_edit_preferences(xpce)
  122     ],
  123     []).
  124menu('&Debug',
  125     [ %'&Trace'             = trace,
  126       %'&Debug mode'        = debug,
  127       %'&No debug mode'     = nodebug,
  128       '&Edit spy points ...' = user:prolog_ide(open_debug_status),
  129       '&Edit exceptions ...' = user:prolog_ide(open_exceptions(@on)),
  130       '&Threads monitor ...' = user:prolog_ide(thread_monitor),
  131       'Debug &messages ...'  = user:prolog_ide(debug_monitor),
  132       'Cross &referencer ...'= user:prolog_ide(xref),
  133       --,
  134       '&Graphical debugger' = user:guitracer
  135     ],
  136     [ before_menu(-)
  137     ]).
  138menu('&Help',
  139     [ '&About ...'                             = about,
  140       '&Help ...'                              = help,
  141       'Browse &PlDoc ...'                      = doc_browser,
  142       --,
  143       'SWI-Prolog website ...'                 = www_open(swipl),
  144       '  &Manual ...'                          = www_open(swipl_man),
  145       '  &FAQ ...'                             = www_open(swipl_faq),
  146       '  &Quick Start ...'                     = www_open(swipl_quick),
  147       '  Mailing &List ...'                    = www_open(swipl_mail),
  148       '  &Download ...'                        = www_open(swipl_download),
  149       '  &Extension packs ...'                 = www_open(swipl_pack),
  150       --,
  151       '&XPCE (GUI) Manual ...'                 = manpce,
  152       --,
  153       '&Check installation'                    = check_installation,
  154       'Submit &Bug report ...'                 = www_open(swipl_bugs)
  155     ],
  156     [ before_menu(-)
  157     ]).
  158
  159
  160init_win_menus :-
  161    (   menu(Menu, Items, Options),
  162        (   memberchk(before_item(Before), Options)
  163        ->  true
  164        ;   Before = (-)
  165        ),
  166        (   memberchk(before_menu(BM), Options)
  167        ->  true
  168        ;   BM = (-)
  169        ),
  170        win_insert_menu(Menu, BM),
  171        (   '$member'(Item, Items),
  172            (   Item = (Label = Action)
  173            ->  true
  174            ;   Item == --
  175            ->  Label = --
  176            ),
  177            win_insert_menu_item(Menu, Label, Before, Action),
  178            fail
  179        ;   true
  180        ),
  181        fail
  182    ;   current_prolog_flag(associated_file, File),
  183        add_to_mru(load, File)
  184    ;   insert_associated_file
  185    ),
  186    refresh_mru.
  187
  188associated_file(File) :-
  189    current_prolog_flag(associated_file, File),
  190    !.
  191associated_file(File) :-
  192    '$cmd_option_val'(script_file, OsFiles),
  193    OsFiles = [OsFile],
  194    !,
  195    prolog_to_os_filename(File, OsFile).
  196
  197insert_associated_file :-
  198    associated_file(File),
  199    !,
  200    file_base_name(File, Base),
  201    atom_concat('Edit &', Base, Label),
  202    win_insert_menu_item('&File', Label, '&New ...', edit(file(File))).
  203insert_associated_file.
  204
  205
  206:- if(current_predicate(win_has_menu/0)).  207:- initialization
  208   (   win_has_menu
  209   ->  init_win_menus
  210   ;   true
  211   ).  212:- endif.  213
  214                 /*******************************
  215                 *            ACTIONS           *
  216                 *******************************/
  217
  218edit_new(File) :-
  219    call(edit(file(File))).         % avoid autoloading
  220
  221www_open(Id) :-
  222    Spec =.. [Id, '.'],
  223    call(expand_url_path(Spec, URL)),
  224    print_message(informational, opening_url(URL)),
  225    call(www_open_url(URL)),        % avoid autoloading
  226    print_message(informational, opened_url(URL)).
  227
  228html_open(Spec) :-
  229    absolute_file_name(Spec, [access(read)], Path),
  230    call(win_shell(open, Path)).
  231
  232:- if(current_predicate(win_message_box/2)).  233
  234about :-
  235    message_to_string(about, AboutSWI),
  236    (   current_prolog_flag(console_menu_version, qt)
  237    ->  message_to_string(about_qt, AboutQt),
  238        format(atom(About), '<p>~w\n<p>~w', [AboutSWI, AboutQt])
  239    ;   About = AboutSWI
  240    ),
  241    atomic_list_concat(Lines, '\n', About),
  242    atomic_list_concat(Lines, '<br>', AboutHTML),
  243    win_message_box(
  244        AboutHTML,
  245        [ title('About swipl-win'),
  246          image(':/swipl.png'),
  247          min_width(700)
  248        ]).
  249
  250:- else.  251
  252about :-
  253    print_message(informational, about).
  254
  255:- endif.  256
  257load(Path) :-
  258    (   \+ current_prolog_flag(associated_file, _)
  259    ->  file_directory_name(Path, Dir),
  260        working_directory(_, Dir),
  261        set_prolog_flag(associated_file, Path)
  262    ;   true
  263    ),
  264    user:load_files(Path).
  265
  266
  267                 /*******************************
  268                 *       HANDLE CALLBACK        *
  269                 *******************************/
  270
  271action(Action) :-
  272    strip_module(Action, Module, Plain),
  273    Plain =.. [Name|Args],
  274    gather_args(Args, Values),
  275    Goal =.. [Name|Values],
  276    call(Module:Goal).
  277
  278gather_args([], []).
  279gather_args([+H0|T0], [H|T]) :-
  280    !,
  281    gather_arg(H0, H),
  282    gather_args(T0, T).
  283gather_args([H|T0], [H|T]) :-
  284    gather_args(T0, T).
  285
  286:- if(current_prolog_flag(console_menu_version, qt)).  287
  288gather_arg(file(open, Title), File) :-
  289    !,
  290    source_types_desc(Desc),
  291    pqConsole:getOpenFileName(Title, _, Desc, File),
  292    add_to_mru(edit, File).
  293
  294gather_arg(file(save, Title), File) :-
  295    source_types_desc(Desc),
  296    pqConsole:getSaveFileName(Title, _, Desc, File),
  297    add_to_mru(edit, File).
  298
  299source_types_desc(Desc) :-
  300    findall(Pattern, prolog_file_pattern(Pattern), Patterns),
  301    atomic_list_concat(Patterns, ' ', Atom),
  302    format(atom(Desc), 'Prolog Source (~w)', [Atom]).
  303
  304:- else.  305
  306gather_arg(file(Mode, Title), File) :-
  307    findall(tuple('Prolog Source', Pattern),
  308            prolog_file_pattern(Pattern),
  309            Tuples),
  310    '$append'(Tuples, [tuple('All files', '*.*')], AllTuples),
  311    Filter =.. [chain|AllTuples],
  312    current_prolog_flag(hwnd, HWND),
  313    working_directory(CWD, CWD),
  314    call(get(@display, win_file_name,       % avoid autoloading
  315             Mode, Filter, Title,
  316             directory := CWD,
  317             owner := HWND,
  318             File)).
  319
  320:- endif.  321
  322prolog_file_pattern(Pattern) :-
  323    user:prolog_file_type(Ext, prolog),
  324    atom_concat('*.', Ext, Pattern).
  325
  326
  327:- if(current_prolog_flag(windows, true)).  328
  329                 /*******************************
  330                 *          APPLICATION         *
  331                 *******************************/
 init_win_app
If Prolog is started using --win_app, try to change directory to <My Documents>\Prolog.
  338init_win_app :-
  339    current_prolog_flag(associated_file, _),
  340    !.
  341init_win_app :-
  342    '$cmd_option_val'(win_app, true),
  343    !,
  344    catch(my_prolog, E, print_message(warning, E)).
  345init_win_app.
  346
  347my_prolog :-
  348    win_folder(personal, MyDocs),
  349    atom_concat(MyDocs, '/Prolog', PrologDir),
  350    (   ensure_dir(PrologDir)
  351    ->  working_directory(_, PrologDir)
  352    ;   working_directory(_, MyDocs)
  353    ).
  354
  355
  356ensure_dir(Dir) :-
  357    exists_directory(Dir),
  358    !.
  359ensure_dir(Dir) :-
  360    catch(make_directory(Dir), E, (print_message(warning, E), fail)).
  361
  362
  363:- initialization
  364   init_win_app.  365
  366:- endif. /*windows*/
  367
  368
  369                 /*******************************
  370                 *             MacOS            *
  371                 *******************************/
  372
  373:- if(current_prolog_flag(console_menu_version, qt)).  374
  375:- multifile
  376    prolog:file_open_event/1.  377
  378:- create_prolog_flag(app_open_first, load, []).  379:- create_prolog_flag(app_open,       edit, []).
 prolog:file_open_event(+Name)
Called when opening a file from the MacOS finder. The action depends on whether this is the first file or not, and defined by one of these flags:

On the first open event, the working directory of the process is changed to the directory holding the file. Action is one of the following:

load
Load the file into Prolog
edit
Open the file in the editor
new_instance
Open the file in a new instance of Prolog and load it there.
  401prolog:file_open_event(Path) :-
  402    (   current_prolog_flag(associated_file, _)
  403    ->  current_prolog_flag(app_open, Action)
  404    ;   current_prolog_flag(app_open_first, Action),
  405        file_directory_name(Path, Dir),
  406        working_directory(_, Dir),
  407        set_prolog_flag(associated_file, Path),
  408        insert_associated_file
  409    ),
  410    must_be(oneof([edit,load,new_instance]), Action),
  411    file_open_event(Action, Path).
  412
  413file_open_event(edit, Path) :-
  414    edit(Path).
  415file_open_event(load, Path) :-
  416    add_to_mru(load, Path),
  417    user:load_files(Path).
  418:- if(current_prolog_flag(apple, true)).  419file_open_event(new_instance, Path) :-
  420    current_app(Me),
  421    print_message(informational, new_instance(Path)),
  422    process_create(path(open), [ '-n', '-a', Me, Path ], []).
  423:- else.  424file_open_event(new_instance, Path) :-
  425    current_prolog_flag(executable, Exe),
  426    process_create(Exe, [Path], [process(_Pid)]).
  427:- endif.  428
  429
  430:- if(current_prolog_flag(apple, true)).  431current_app(App) :-
  432    current_prolog_flag(executable, Exe),
  433    file_directory_name(Exe, MacOSDir),
  434    atom_concat(App, '/Contents/MacOS', MacOSDir).
 go_home_on_plain_app_start is det
On Apple, we start in the users home dir if the application is started by opening the app directly.
  441go_home_on_plain_app_start :-
  442    current_prolog_flag(os_argv, [_Exe]),
  443    current_app(App),
  444    file_directory_name(App, Above),
  445    working_directory(PWD, PWD),
  446    same_file(PWD, Above),
  447    expand_file_name(~, [Home]),
  448    !,
  449    working_directory(_, Home).
  450go_home_on_plain_app_start.
  451
  452:- initialization
  453    go_home_on_plain_app_start.  454
  455:- endif.  456:- endif.  457
  458:- if(current_predicate(win_current_preference/3)).  459
  460mru_info('&File', 'Edit &Recent', 'MRU2',    path, edit).
  461mru_info('&File', 'Load &Recent', 'MRULoad', path, load).
  462
  463add_to_mru(Action, File) :-
  464    mru_info(_Top, _Menu, PrefGroup, PrefKey, Action),
  465    (   win_current_preference(PrefGroup, PrefKey, CPs), nonvar(CPs)
  466    ->  (   select(File, CPs, Rest)
  467        ->  Updated = [File|Rest]
  468        ;   length(CPs, Len),
  469            Len > 10
  470        ->  append(CPs1, [_], CPs),
  471            Updated = [File|CPs1]
  472        ;   Updated = [File|CPs]
  473        )
  474    ;   Updated = [File]
  475    ),
  476    win_set_preference(PrefGroup, PrefKey, Updated),
  477    refresh_mru.
  478
  479refresh_mru :-
  480    (   mru_info(FileMenu, Menu, PrefGroup, PrefKey, Action),
  481        win_current_preference(PrefGroup, PrefKey, CPs),
  482        maplist(action_path_menu(Action), CPs, Labels, Actions),
  483        win_insert_menu_item(FileMenu, Menu/Labels, -, Actions),
  484        fail
  485    ;   true
  486    ).
  487
  488action_path_menu(ActionItem, Path, Label, win_menu:Action) :-
  489    file_base_name(Path, Label),
  490    Action =.. [ActionItem, Path].
  491
  492:- else.  493
  494add_to_mru(_, _).
  495refresh_mru.
  496
  497:- endif.  498
  499
  500                 /*******************************
  501                 *            MESSAGES          *
  502                 *******************************/
  503
  504:- multifile
  505    prolog:message/3.  506
  507prolog:message(opening_url(Url)) -->
  508    [ 'Opening ~w ... '-[Url], flush ].
  509prolog:message(opened_url(_Url)) -->
  510    [ at_same_line, 'ok' ].
  511prolog:message(new_instance(Path)) -->
  512    [ 'Opening new Prolog instance for ~p'-[Path] ].
  513:- if(current_prolog_flag(console_menu_version, qt)).  514prolog:message(about_qt) -->
  515    [ 'Qt-based console by Carlo Capelli' ].
  516:- endif.