; --------------------------------------------------------------------------------------------; Copyright (c) Fantaisie Software. All rights reserved.; Dual licensed under the GPL and Fantaisie Software licenses.; See LICENSE and LICENSE-FANTAISIE in the project root for license information.; --------------------------------------------------------------------------------------------; linux specific file:CompilerIf #CompileLinuxStructure XClientMessageEventtype.l ; intCompilerIf #PB_Compiler_Processor = #PB_Processor_x64alignment1.lCompilerEndIfserial.i ; unsigned long /* # of last request processed by server */send_event.l ; Bool (=int) /* true if this came from a SendEvent request */CompilerIf #PB_Compiler_Processor = #PB_Processor_x64alignment2.lCompilerEndIf*display ; pointer /* Display the event was read from */window.i ; Window (= pointer)message_type.i; Atom (= pointer)format.l ; intCompilerIf #PB_Compiler_Processor = #PB_Processor_x64alignment3.lCompilerEndIfStructureUnionb.b[20] ; chars.w[10] ; shortl.i[5] ; long is 64bit on Linux64!EndStructureUnionEndStructureGlobal AlreadyRunningProcedure OSStartupCode()Shared DetectedGUITerminal,ドル GUITerminalParameters$ ; for the debuggerHome$ = GetEnvironmentVariable("HOME")If Right(Home,ドル 1) <> #SeparatorHome$ + #SeparatorEndIf; If the PUREBASIC_HOME is not set, we use the path to the purebasic executable as a reference.; This way IDE compilation should work completely without the PUREBASIC_HOME. (so it is only needed; for commandline compilation). This should be easier to setup for people.;If PureBasicPath$ = "" ; only change if not set by commandline -bCompilerIf #SpiderBasicPureBasicPath$ = GetEnvironmentVariable("SPIDERBASIC_HOME")CompilerElsePureBasicPath$ = GetEnvironmentVariable("PUREBASIC_HOME")CompilerEndIfIf PureBasicPath$ = ""PureBasicPath$ = GetPathPart(ProgramFilename()); Not an absolute path, combine it with the current directory to have an absolute oneIf Left(PureBasicPath,ドル 1) <> "/"PureBasicPath$ = GetCurrentDirectory() + PureBasicPath$EndIf; cut the compilers dir partIf Right(PureBasicPath,ドル 10) = "compilers/"PureBasicPath$ = Left(PureBasicPath,ドル Len(PureBasicPath$)-10)ElseIf Right(PureBasicPath,ドル 9) = "compilers"PureBasicPath$ = Left(PureBasicPath,ドル Len(PureBasicPath$)-9)ElsePureBasicPath$ = "" ; Not a PureBasic/SpiderBasic root pathEndIfEndIfEndIf; check if what we have here is a valid path. (if /proc is not mounted, ProgramFileName() may return a relative pathIf FileSize(PureBasicPath$) <> -2CompilerIf #SpiderBasicMessageRequester("Error", "Can't locate the SpiderBasic install directory."+#LF$+"Please export the 'SPIDERBASIC_HOME' env variable before starting the IDE.", #PB_MessageRequester_Error)CompilerElseMessageRequester("Error", "Can't locate the PureBasic install directory."+#LF$+"Please export the 'PUREBASIC_HOME' env variable before starting the IDE.", #PB_MessageRequester_Error)CompilerEndIfEndIfDebug "PureBasicPath$ = " + PureBasicPath$If Right(PureBasicPath,ドル 1) <> #SeparatorPureBasicPath$ + #SeparatorEndIf; Don't replace space with "\ " as all PureBasic commands like OpenFile() expect a real space.;; If FindString(PureBasicPath,ドル "\ ", 1) = 0; PureBasicPath$ = ReplaceString(PureBasicPath,ドル " ", "\ ") ; this is only needed here, to work on the commandline; EndIfTempPath$ = "/tmp/"If PreferencesFile$ = "" ; Only change if not set by commandlinePreferencesFile$ = PureBasicConfigPath() + #PreferenceFileName$EndIfIf AddToolsFile$ = "" ; Only change if not set by commandlineAddToolsFile$ = PureBasicConfigPath() + "tools.prefs"EndIfIf TemplatesFile$ = "" ; Only change if not set by commandlineTemplatesFile$ = PureBasicConfigPath() + "templates.prefs"EndIfIf HistoryDatabaseFile$ = "" ; Only change if not set by commandlineHistoryDatabaseFile$ = PureBasicConfigPath() + "history.db"EndIfIf SourcePathSet = 0; It's important to point on the examples when the path is not set as when your run PureBasic for the first; time, you want to open examples to test them. This value can be changed in the prefs and won't be; used if another pref is found;SourcePath$ = PureBasicPath$ + "examples/"EndIfCompilerIf #SpiderBasicRunOnceFile$ = TempPath$ + ".sbrunonce.txt"CompilerElseRunOnceFile$ = TempPath$ + ".pbrunonce.txt"CompilerEndIf;Debug "PureBasicPath: "+PureBasicPath$;Debug "Preferences: "+ PreferencesFile$;Debug "Tools settings: "+AddToolsFile$ButtonBackgroundColor = GetButtonBackgroundColor(); Try to detect a gui terminal program, where the debugger can be displayed in...; Note: somehow, when the title option is set, often it does not execute correctly (for example in gnome-terminal); so remove them all;If system_(ToAscii("which gnome-terminal > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = "-- "ElseIf system_(ToAscii("which konsole > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = " -e "ElseIf system_(ToAscii("which aterm > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = " -e "ElseIf system_(ToAscii("which mlterm > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = " -e "ElseIf system_(ToAscii("which rxvt > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = " -e "ElseIf system_(ToAscii("which xterm > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = " -e "ElseIf system_(ToAscii("which lxterminal > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = " -e "ElseIf system_(ToAscii("which io.elementary.terminal > "+TempPath$+"PB_TerminalTest.txt 2>/dev/null")) = 0GUITerminalParameters$ = " -e "ElseGUITerminalParameters$ = ""EndIf; read the which output, to get the full path (as the internal debugger doesn't search the PATH environment;If GUITerminalParameters$ <> ""If ReadFile(#FILE_CompilerInfo, TempPath$+"PB_TerminalTest.txt")DetectedGUITerminal$ = ReadString(#FILE_CompilerInfo)CloseFile(#FILE_CompilerInfo)ElseDetectedGUITerminal$ = ""EndIfEndIfDeleteFile(TempPath$+"PB_TerminalTest.txt")ProcedureReturn 1EndProcedureProcedure OSEndCode()If AlreadyRunning = 0DeleteFile(TempPath$ + ".purebasic.running")EndIf; still used for IDE->Debugger communication when using a FIFODeleteFile(TempPath$ + ".purebasic.out")EndProcedureDeclare RunOnce_MessageFilter(*XEvent.XClientMessageEvent, *Event.GdkEventClient, user_data); determine things like StatusBarHeight once after the GUI is created.Procedure GetWindowMetrics()StatusbarHeight = StatusBarHeight(#STATUSBAR)ToolbarHeight = 35ToolbarTopOffset = 0; MenuHeight = MenuHeight() ; returns a fixed value!;CompilerIf #CompileLinuxGtkMenuSize.GtkRequisition;gtk_widget_size_request_(MenuID(#MENU), @MenuSize)MenuHeight = MenuSize\heightCompilerElseMenuHeight = 0CompilerEndIf; Set up the callback for the RunOnce event; (don't do this in OSStartupCode(), because at this point it is not determined if there is already an editor Window);CompilerIf #CompileLinuxGtk2 ; TODO-GTK3 TODO-QTgdk_add_client_message_filter_(gdk_atom_intern_("PureBasic_RunOnceSignal", 0), @RunOnce_MessageFilter(), 0)CompilerEndIfEndProcedureProcedure LoadEditorFonts(); The font still needs to be loaded for the Preferences displayIf LoadFont(#FONT_Editor, EditorFontName,ドル EditorFontSize)EditorFontID = FontID(#FONT_Editor)EndIfEditorBoldFontName$ = EditorFontName$EndProcedureProcedure UpdateToolbarView()CompilerIf #CompileLinuxGtkIf ShowMainToolbargtk_widget_show_(*MainToolbar)Elsegtk_widget_hide_(*MainToolbar)EndIfCompilerElseIf ShowMainToolbarQtScript("toolbar(" + #TOOLBAR + ").show()")ElseQtScript("toolbar(" + #TOOLBAR + ").hide()")EndIfCompilerEndIfEndProcedureProcedure RunOnceSignalReceived()If ReadFile(#FILE_RunOnce, RunOnceFile$)While Eof(#FILE_RunOnce) = 0FileName$ = ReadString(#FILE_RunOnce);If Left(FileName,ドル 7) = "--LINE "; ; apply the current line commandline option; InitialSourceLine = Val(Right(FileName,ドル Len(FileName$)-7)); If InitialSourceLine > 0 And InitialSourceLine < GetLinesCount(*ActiveSource) ; apply the -l option; ChangeActiveLine(InitialSourceLine, -5); EndIf;ElseIf FileName$ <> ""; LoadSourceFile(FileName$);EndIf; NOTE: Trying to open the files from here will cause the IDE to lock up on Linux x64,; so we add the names to this list (which is empty after startup), and the main loop; checks for the size of this list and opens it from there (see PureBasic.pb);; We still have the file reading in here, as all this could happen multiple times in succession; when PB files are opened by a file explorer etc.;AddElement(OpenFilesCommandLine())OpenFilesCommandLine() = FileName$WendCloseFile(#FILE_RunOnce)EndIfDeleteFile(RunOnceFile$); Still need the SetWindowForeground here, as apparently it has no effect if we delay it until after the X messageSetWindowForeground(#WINDOW_Main);ResizeMainWindow()EndProcedureProcedureC RunOnce_MessageFilter(*XEvent.XClientMessageEvent, *Event.GdkEventClient, user_data)Static LastEventSenderIf Editor_RunOnceIf *XEvent\l[0] <> LastEventSenderRunOnceSignalReceived()LastEventSender = *XEvent\l[0]EndIfProcedureReturn #GDK_FILTER_REMOVE ; there is only 1 instance, so no need to send this message furtherElseProcedureReturn #GDK_FILTER_CONTINUEEndIfEndProcedure; Return true of PID is a running instance of this IDEProcedure IsRunningIDEInstance(PID)IsRunning = 0; the other Instance isn't running (kill with '0' doesn't kill if it is still running, but returns > 0 if the PID is invalid)If kill_(PID, 0) = 0;; if the IDE crashes, and then the PC is restarted, the PID in this file could be; in use by another process, which will stop the IDE from starting.; /proc/PID/exe is a symbolic link, so simply check if that leads to the IDE exe;; This code is what ProgramFilename() does, so it can be compared;Executable$ = ProgramFilename()length = Len(Executable$)File$ = "/proc/"+Str(PID)+"/exe"*Buffer = AllocateMemory(length+20) ; do not use the exe length alone, as else we cannot tell if the link name is longer than thatIf *Bufferreadlength = readlink_(ToAscii(File$), *Buffer, length+20)If readlength = length And PeekS(*Buffer, length, #PB_Ascii) = Executable$ ; *Buffer is not 0-terminated!IsRunning = 1EndIfFreeMemory(*Buffer)EndIfEndIfProcedureReturn IsRunningEndProcedureProcedure IsEditorRunning()IsRunning = 0If ReadFile(#FILE_RunOnce, TempPath$ + ".purebasic.running")PID = Val(ReadString(#FILE_RunOnce))CloseFile(#FILE_RunOnce)IsRunning = IsRunningIDEInstance(PID)If IsRunning = 0DeleteFile(TempPath$ + ".purebasic.running") ; this was the file of a dead instance so delete it.EndIfEndIfIf IsRunning = 0If CreateFile(#FILE_RunOnce, TempPath$ + ".purebasic.running")WriteString(#FILE_RunOnce, Str(getpid_()))CloseFile(#FILE_RunOnce)EndIfEndIfAlreadyRunning = IsRunningProcedureReturn IsRunningEndProcedureProcedure EmitRunOnceSignal()CompilerIf #CompileLinuxGtk2 ; TODO-GTK3 TODO-QTEvent.GdkEventClientEvent\type = #GDK_CLIENT_EVENTEvent\send_event = 1Event\message_type = gdk_atom_intern_("PureBasic_RunOnceSignal", 0)Event\data_format = 32Event\l[0] = getpid_() ; identify the sender, to filter out multiple arriving signalsgdk_event_send_clientmessage_toall_(@Event)CompilerEndIfEndProcedureProcedure RunOnce_Startup(InitialSourceLine)Result = #False ; do not close IDEIf IsEditorRunning()If CreateFile(#FILE_RunOnce, RunOnceFile$)ForEach OpenFilesCommandline()WriteStringN(#FILE_RunOnce, OpenFilesCommandline())Next OpenFilesCommandline()If InitialSourceLine <> -1WriteStringN(#FILE_RunOnce, "--LINE "+Str(InitialSourceLine)) ; send this option on to the opened IDE (always as last one!)EndIfCloseFile(#FILE_RunOnce)EmitRunOnceSignal()Result = #True ; close IDEEndIfEndIfProcedureReturn ResultEndProcedureProcedure RunOnce_UpdateSetting()If Editor_RunOnceIf CreateFile(#FILE_RunOnce, TempPath$ + ".purebasic.running")WriteString(#FILE_RunOnce, Str(getpid_()))CloseFile(#FILE_RunOnce)EndIfElseDeleteFile(TempPath$ + ".purebasic.running")EndIfEndProcedure; Dead session detectionProcedure Session_IsRunning(OSSessionID$); The OSSessionID is the PID of the processPID = Val(OSSessionID$)ProcedureReturn IsRunningIDEInstance(PID)EndProcedureProcedure.s Session_Start(); Return the current PID as the OSSessionID; This can then be used to delect if the session is still activeProcedureReturn Str(getpid_())EndProcedureProcedure Session_End(OSSessionID$); No need to clean up anythingEndProcedureCompilerIf #CompileLinuxGtkProcedureC AutoComplete_GtkFocusSignal(*Window, *Event, user_data)If AutoCompleteWindowOpenIf user_data+500 < ElapsedMilliseconds() ; to ignore the immediate lost focus that seems to be reportet on MandrakeAutoComplete_Close()EndIfEndIfProcedureReturn 1EndProcedureProcedureC AutoComplete_GtkTabHandler(*Widget, *Event.GdkEventKey, user_data)If AutoCompleteWindowOpenAccelerators = g_object_get_data_(gtk_widget_get_toplevel_(*Widget), "pb_accelerators")If AcceleratorsKey = *Event\keyval; The TAB shortcut willn't be processed correctly, so catch it here;If Key = $FF09 And KeyboardShortcuts(#MENU_AutoComplete_OK) = #PB_Shortcut_TabAutoComplete_Insert()ProcedureReturn 1EndIfIf *Event\type = #GDK_KEY_PRESS; gtk_accel_groups_activate_() works as well for our case, but it's not sure than the shortcut is; really in our accelerator list, so check it. Note the '& $F' for the query, without which it fails;If gtk_accel_group_query_(Accelerators, Key, *Event\state & $F, @NbEntriesFound)ProcedureReturn gtk_accel_groups_activate_(gtk_widget_get_toplevel_(*Widget), Key, *Event\state)EndIfEndIfEndIf; close autocomplete on PGUP/DOWN, LEFT and RIGHTIf *Event\keyval = #GDK_Prior Or *Event\keyval = #GDK_Next Or *Event\keyval = #GDK_Left Or *Event\keyval = #GDK_RightAutoComplete_Close()ElseIf *Event\keyval <> $FF52 And *Event\keyval <> $FF54gtk_widget_event_(GadgetID(*ActiveSource\EditorGadget), *Event) ; pass on any events except for up/down to the editorProcedureReturn 1EndIfEndIfProcedureReturn 0EndProcedureCompilerEndIfCompilerIf #CompileLinuxQtProcedureC AutoComplete_QtEventFilter(*Event)If AutoCompleteWindowOpenType = QT_EventType(*Event)If Type = 9 ; QEvent::FocusOutAutoComplete_Close()ProcedureReturn 1 ; event handledElseIf Type = 6 Or Type = 7 ; QEvent::KeyPress or QEvent::KeyReleaseKey = QT_EventKey(*Event); Close on PGUP/DOWN, LEFT and RIGHTIf Key = 01000016ドル Or Key = 01000017ドル Or Key = 01000014ドル Or Key = 01000012ドルAutoComplete_Close()ProcedureReturn 1 ; event handled; Normal gadget handling for up and downElseIf Key = 01000013ドル Or Key = 01000015ドルProcedureReturn 0; Tab shortcut does not work with the forwarding trick below; ElseIf Type = 6 And Key = 01000001ドル And KeyboardShortcuts(#MENU_AutoComplete_OK) = #PB_Shortcut_Tab; AutoComplete_Insert(); ProcedureReturn 1; Send all other keys to the editorElseQT_SendEvent(GadgetID(*ActiveSource\EditorGadget), *Event)ProcedureReturn 1 ; event handledEndIfEndIfEndIfProcedureReturn 0 ; do default event handlingEndProcedureCompilerEndIfProcedure AutoComplete_SetFocusCallback()CompilerIf #CompileLinuxGtk; set the tab handler for the gadget;GtkSignalConnect(GadgetID(#GADGET_AutoComplete_List), "key-press-event", @AutoComplete_GtkTabHandler(), 0)GtkSignalConnect(GadgetID(#GADGET_AutoComplete_List), "key-release-event", @AutoComplete_GtkTabHandler(), 0); set up a callback to close the autocomplete window if the user selects some other window;GtkSignalConnect(WindowID(#WINDOW_AutoComplete), "focus-out-event", @AutoComplete_GtkFocusSignal(), ElapsedMilliseconds())CompilerElse; For both key and focus eventsQT_SetEventFilter(GadgetID(#GADGET_AutoComplete_List), @AutoComplete_QtEventFilter())CompilerEndIfEndProcedureProcedure AutoComplete_AdjustWindowSize(MaxWidth, MaxHeight)EndProcedureProcedure ToolsPanel_ApplyColors(Gadget); Disable ToolsPanel colors for Linux, because of the background; color bug of GtkTreeView based gadgets that we have no fix for so far.; Better no color than this ugly color change.;; NOTE: This bug seems to be gone, all is working OK in ubuntu 11.04 and PB v4.70If Gadget = propgridgrid_SetGadgetColor(Gadget, #Grid_Color_Background, ToolsPanelBackColor)grid_SetDefaultStyle(Gadget,P_FontGrid, #P_FontGridSize, ToolsPanelFrontColor)ElseIf ToolsPanelUseColorsSetGadgetColor(Gadget, #PB_Gadget_FrontColor, ToolsPanelFrontColor)SetGadgetColor(Gadget, #PB_Gadget_BackColor, ToolsPanelBackColor)EndIfIf ToolsPanelFontID <> #PB_DefaultSetGadgetFont(Gadget, ToolsPanelFontID)EndIfEndIfEndProcedureProcedure IsScreenReaderActive()ProcedureReturn #FalseEndProcedureCompilerEndIf
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。