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:- autoload(library(apply),[maplist/4]).   41:- autoload(library(edit),[edit/1]).   42:- autoload(library(lists),[select/3,append/3]).   43:- autoload(library(pce),[get/8]).   44:- autoload(library(www_browser),[expand_url_path/2,www_open_url/1]).   45
   46
   47:- set_prolog_flag(generate_debug_info, false).   48:- op(200, fy, @).   49:- 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. */

   57:- if(current_prolog_flag(console_menu_version, qt)).   58% The traditional swipl-win.exe predefines some menus.  The Qt version
   59% does not.  Here, we predefine the same menus to make the remainder
   60% compatiple.
   61menu('&File',
   62     [ 'E&xit' = pqConsole:quit_console
   63     ],
   64     [
   65     ]).
   66menu('&Edit',
   67     [ '&Copy'  = pqConsole:copy,
   68       '&Paste' = pqConsole:paste
   69     ],
   70     []).
   71menu('&Settings',
   72     [ '&Font ...' = pqConsole:select_font,
   73       '&Colors ...' = pqConsole:select_ANSI_term_colors
   74     ],
   75     []).
   76menu('&Run',
   77     [ '&Interrupt' = interrupt,
   78       '&New thread' = interactor
   79     ],
   80     []).
   81
   82menu(File,
   83     [ '&Consult ...' = action(user:load_files(+file(open,
   84                                                     'Load file into Prolog'),
   85                                               [silent(false)])),
   86       '&Edit ...'    = action(user:edit(+file(open,
   87                                               'Edit existing file'))),
   88       '&New ...'     = action(edit_new(+file(save,
   89                                              'Create new Prolog source'))),
   90       --
   91     | MRU
   92     ], [before_item('E&xit')]) :-
   93    File = '&File',
   94    findall(Mru=true, mru_info(File, Mru, _, _, _), MRU, MRUTail),
   95    MRUTail = [ --,
   96                '&Reload modified files' = user:make,
   97                --,
   98                '&Navigator ...' = prolog_ide(open_navigator),
   99                --
  100              ].
  101
  102:- else.  103
  104menu('&File',
  105     [ '&Consult ...' = action(user:load_files(+file(open,
  106                                                     'Load file into Prolog'),
  107                                               [silent(false)])),
  108       '&Edit ...'    = action(user:edit(+file(open,
  109                                               'Edit existing file'))),
  110       '&New ...'     = action(edit_new(+file(save,
  111                                              'Create new Prolog source'))),
  112       --,
  113       '&Reload modified files' = user:make,
  114       --,
  115       '&Navigator ...' = prolog_ide(open_navigator),
  116       --
  117     ],
  118     [ before_item('&Exit')
  119     ]).
  120:- endif.  121
  122menu('&Settings',
  123     [ --,
  124       '&User init file ...'  = prolog_edit_preferences(prolog),
  125       '&GUI preferences ...' = prolog_edit_preferences(xpce)
  126     ],
  127     []).
  128menu('&Debug',
  129     [ %'&Trace'             = trace,
  130       %'&Debug mode'        = debug,
  131       %'&No debug mode'     = nodebug,
  132       '&Edit spy points ...' = user:prolog_ide(open_debug_status),
  133       '&Edit exceptions ...' = user:prolog_ide(open_exceptions(@on)),
  134       '&Threads monitor ...' = user:prolog_ide(thread_monitor),
  135       'Debug &messages ...'  = user:prolog_ide(debug_monitor),
  136       'Cross &referencer ...'= user:prolog_ide(xref),
  137       --,
  138       '&Graphical debugger' = user:guitracer
  139     ],
  140     [ before_menu(-)
  141     ]).
  142menu('&Help',
  143     [ '&About ...'                             = about,
  144       '&Help ...'                              = help,
  145       'Browse &PlDoc ...'                      = doc_browser,
  146       --,
  147       'SWI-Prolog website ...'                 = www_open(swipl),
  148       '  &Manual ...'                          = www_open(swipl_man),
  149       '  &FAQ ...'                             = www_open(swipl_faq),
  150       '  &Quick Start ...'                     = www_open(swipl_quick),
  151       '  Mailing &List ...'                    = www_open(swipl_mail),
  152       '  &Download ...'                        = www_open(swipl_download),
  153       '  &Extension packs ...'                 = www_open(swipl_pack),
  154       --,
  155       '&XPCE (GUI) Manual ...'                 = manpce,
  156       --,
  157       '&Check installation'                    = check_installation,
  158       'Submit &Bug report ...'                 = www_open(swipl_bugs)
  159     ],
  160     [ before_menu(-)
  161     ]).
  162
  163
  164init_win_menus :-
  165    (   menu(Menu, Items, Options),
  166        (   memberchk(before_item(Before), Options)
  167        ->  true
  168        ;   Before = (-)
  169        ),
  170        (   memberchk(before_menu(BM), Options)
  171        ->  true
  172        ;   BM = (-)
  173        ),
  174        win_insert_menu(Menu, BM),
  175        (   '$member'(Item, Items),
  176            (   Item = (Label = Action)
  177            ->  true
  178            ;   Item == --
  179            ->  Label = --
  180            ),
  181            win_insert_menu_item(Menu, Label, Before, Action),
  182            fail
  183        ;   true
  184        ),
  185        fail
  186    ;   current_prolog_flag(associated_file, File),
  187        add_to_mru(load, File)
  188    ;   insert_associated_file
  189    ),
  190    refresh_mru.
  191
  192associated_file(File) :-
  193    current_prolog_flag(associated_file, File),
  194    !.
  195associated_file(File) :-
  196    '$cmd_option_val'(script_file, OsFiles),
  197    OsFiles = [OsFile],
  198    !,
  199    prolog_to_os_filename(File, OsFile).
  200
  201insert_associated_file :-
  202    associated_file(File),
  203    !,
  204    file_base_name(File, Base),
  205    atom_concat('Edit &', Base, Label),
  206    win_insert_menu_item('&File', Label, '&New ...', edit(file(File))).
  207insert_associated_file.
  208
  209
  210:- if(current_predicate(win_has_menu/0)).  211:- initialization
  212   (   win_has_menu
  213   ->  init_win_menus
  214   ;   true
  215   ).  216:- endif.  217
  218                 /*******************************
  219                 *            ACTIONS           *
  220                 *******************************/
  221
  222edit_new(File) :-
  223    call(edit(file(File))).         % avoid autoloading
  224
  225www_open(Id) :-
  226    Spec =.. [Id, '.'],
  227    call(expand_url_path(Spec, URL)),
  228    print_message(informational, opening_url(URL)),
  229    call(www_open_url(URL)),        % avoid autoloading
  230    print_message(informational, opened_url(URL)).
  231
  232html_open(Spec) :-
  233    absolute_file_name(Spec, [access(read)], Path),
  234    call(win_shell(open, Path)).
  235
  236:- if(current_predicate(win_message_box/2)).  237
  238about :-
  239    message_to_string(about, AboutSWI),
  240    (   current_prolog_flag(console_menu_version, qt)
  241    ->  message_to_string(about_qt, AboutQt),
  242        format(atom(About), '<p>~w\n<p>~w', [AboutSWI, AboutQt])
  243    ;   About = AboutSWI
  244    ),
  245    atomic_list_concat(Lines, '\n', About),
  246    atomic_list_concat(Lines, '<br>', AboutHTML),
  247    win_message_box(
  248        AboutHTML,
  249        [ title('About swipl-win'),
  250          image(':/swipl.png'),
  251          min_width(700)
  252        ]).
  253
  254:- else.  255
  256about :-
  257    print_message(informational, about).
  258
  259:- endif.  260
  261load(Path) :-
  262    (   \+ current_prolog_flag(associated_file, _)
  263    ->  file_directory_name(Path, Dir),
  264        working_directory(_, Dir),
  265        set_prolog_flag(associated_file, Path)
  266    ;   true
  267    ),
  268    user:load_files(Path).
  269
  270
  271                 /*******************************
  272                 *       HANDLE CALLBACK        *
  273                 *******************************/
  274
  275action(Action) :-
  276    strip_module(Action, Module, Plain),
  277    Plain =.. [Name|Args],
  278    gather_args(Args, Values),
  279    Goal =.. [Name|Values],
  280    call(Module:Goal).
  281
  282gather_args([], []).
  283gather_args([+H0|T0], [H|T]) :-
  284    !,
  285    gather_arg(H0, H),
  286    gather_args(T0, T).
  287gather_args([H|T0], [H|T]) :-
  288    gather_args(T0, T).
  289
  290:- if(current_prolog_flag(console_menu_version, qt)).  291
  292gather_arg(file(open, Title), File) :-
  293    !,
  294    source_types_desc(Desc),
  295    pqConsole:getOpenFileName(Title, _, Desc, File),
  296    add_to_mru(edit, File).
  297
  298gather_arg(file(save, Title), File) :-
  299    source_types_desc(Desc),
  300    pqConsole:getSaveFileName(Title, _, Desc, File),
  301    add_to_mru(edit, File).
  302
  303source_types_desc(Desc) :-
  304    findall(Pattern, prolog_file_pattern(Pattern), Patterns),
  305    atomic_list_concat(Patterns, ' ', Atom),
  306    format(atom(Desc), 'Prolog Source (~w)', [Atom]).
  307
  308:- else.  309
  310gather_arg(file(Mode, Title), File) :-
  311    findall(tuple('Prolog Source', Pattern),
  312            prolog_file_pattern(Pattern),
  313            Tuples),
  314    '$append'(Tuples, [tuple('All files', '*.*')], AllTuples),
  315    Filter =.. [chain|AllTuples],
  316    current_prolog_flag(hwnd, HWND),
  317    working_directory(CWD, CWD),
  318    call(get(@display, win_file_name,       % avoid autoloading
  319             Mode, Filter, Title,
  320             directory := CWD,
  321             owner := HWND,
  322             File)).
  323
  324:- endif.  325
  326prolog_file_pattern(Pattern) :-
  327    user:prolog_file_type(Ext, prolog),
  328    atom_concat('*.', Ext, Pattern).
  329
  330
  331:- if(current_prolog_flag(windows, true)).  332
  333                 /*******************************
  334                 *          APPLICATION         *
  335                 *******************************/
 init_win_app
If Prolog is started using --win_app, try to change directory to <My Documents>\Prolog.
  342init_win_app :-
  343    current_prolog_flag(associated_file, _),
  344    !.
  345init_win_app :-
  346    '$cmd_option_val'(win_app, true),
  347    !,
  348    catch(my_prolog, E, print_message(warning, E)).
  349init_win_app.
  350
  351my_prolog :-
  352    win_folder(personal, MyDocs),
  353    atom_concat(MyDocs, '/Prolog', PrologDir),
  354    (   ensure_dir(PrologDir)
  355    ->  working_directory(_, PrologDir)
  356    ;   working_directory(_, MyDocs)
  357    ).
  358
  359
  360ensure_dir(Dir) :-
  361    exists_directory(Dir),
  362    !.
  363ensure_dir(Dir) :-
  364    catch(make_directory(Dir), E, (print_message(warning, E), fail)).
  365
  366
  367:- initialization
  368   init_win_app.  369
  370:- endif. /*windows*/
  371
  372
  373                 /*******************************
  374                 *             MacOS            *
  375                 *******************************/
  376
  377:- if(current_prolog_flag(console_menu_version, qt)).  378
  379:- multifile
  380    prolog:file_open_event/1.  381
  382:- create_prolog_flag(app_open_first, load, []).  383:- 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.
  405prolog:file_open_event(Path) :-
  406    (   current_prolog_flag(associated_file, _)
  407    ->  current_prolog_flag(app_open, Action)
  408    ;   current_prolog_flag(app_open_first, Action),
  409        file_directory_name(Path, Dir),
  410        working_directory(_, Dir),
  411        set_prolog_flag(associated_file, Path),
  412        insert_associated_file
  413    ),
  414    must_be(oneof([edit,load,new_instance]), Action),
  415    file_open_event(Action, Path).
  416
  417file_open_event(edit, Path) :-
  418    edit(Path).
  419file_open_event(load, Path) :-
  420    add_to_mru(load, Path),
  421    user:load_files(Path).
  422:- if(current_prolog_flag(apple, true)).  423file_open_event(new_instance, Path) :-
  424    current_app(Me),
  425    print_message(informational, new_instance(Path)),
  426    process_create(path(open), [ '-n', '-a', Me, Path ], []).
  427:- else.  428file_open_event(new_instance, Path) :-
  429    current_prolog_flag(executable, Exe),
  430    process_create(Exe, [Path], [process(_Pid)]).
  431:- endif.  432
  433
  434:- if(current_prolog_flag(apple, true)).  435current_app(App) :-
  436    current_prolog_flag(executable, Exe),
  437    file_directory_name(Exe, MacOSDir),
  438    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.
  445go_home_on_plain_app_start :-
  446    current_prolog_flag(os_argv, [_Exe]),
  447    current_app(App),
  448    file_directory_name(App, Above),
  449    working_directory(PWD, PWD),
  450    same_file(PWD, Above),
  451    expand_file_name(~, [Home]),
  452    !,
  453    working_directory(_, Home).
  454go_home_on_plain_app_start.
  455
  456:- initialization
  457    go_home_on_plain_app_start.  458
  459:- endif.  460:- endif.  461
  462:- if(current_predicate(win_current_preference/3)).  463
  464mru_info('&File', 'Edit &Recent', 'MRU2',    path, edit).
  465mru_info('&File', 'Load &Recent', 'MRULoad', path, load).
  466
  467add_to_mru(Action, File) :-
  468    mru_info(_Top, _Menu, PrefGroup, PrefKey, Action),
  469    (   win_current_preference(PrefGroup, PrefKey, CPs), nonvar(CPs)
  470    ->  (   select(File, CPs, Rest)
  471        ->  Updated = [File|Rest]
  472        ;   length(CPs, Len),
  473            Len > 10
  474        ->  append(CPs1, [_], CPs),
  475            Updated = [File|CPs1]
  476        ;   Updated = [File|CPs]
  477        )
  478    ;   Updated = [File]
  479    ),
  480    win_set_preference(PrefGroup, PrefKey, Updated),
  481    refresh_mru.
  482
  483refresh_mru :-
  484    (   mru_info(FileMenu, Menu, PrefGroup, PrefKey, Action),
  485        win_current_preference(PrefGroup, PrefKey, CPs),
  486        maplist(action_path_menu(Action), CPs, Labels, Actions),
  487        win_insert_menu_item(FileMenu, Menu/Labels, -, Actions),
  488        fail
  489    ;   true
  490    ).
  491
  492action_path_menu(ActionItem, Path, Label, win_menu:Action) :-
  493    file_base_name(Path, Label),
  494    Action =.. [ActionItem, Path].
  495
  496:- else.  497
  498add_to_mru(_, _).
  499refresh_mru.
  500
  501:- endif.  502
  503
  504                 /*******************************
  505                 *            MESSAGES          *
  506                 *******************************/
  507
  508:- multifile
  509    prolog:message/3.  510
  511prolog:message(opening_url(Url)) -->
  512    [ 'Opening ~w ... '-[Url], flush ].
  513prolog:message(opened_url(_Url)) -->
  514    [ at_same_line, 'ok' ].
  515prolog:message(new_instance(Path)) -->
  516    [ 'Opening new Prolog instance for ~p'-[Path] ].
  517:- if(current_prolog_flag(console_menu_version, qt)).  518prolog:message(about_qt) -->
  519    [ 'Qt-based console by Carlo Capelli' ].
  520:- endif.