diff options
Diffstat (limited to 'DevTools')
-rw-r--r-- | DevTools/HackStudio/Makefile | 3 | ||||
-rw-r--r-- | DevTools/HackStudio/TerminalWrapper.cpp | 95 | ||||
-rw-r--r-- | DevTools/HackStudio/TerminalWrapper.h | 16 | ||||
-rw-r--r-- | DevTools/HackStudio/main.cpp | 10 |
4 files changed, 120 insertions, 4 deletions
diff --git a/DevTools/HackStudio/Makefile b/DevTools/HackStudio/Makefile index d23b1d60a6..23bcd506eb 100644 --- a/DevTools/HackStudio/Makefile +++ b/DevTools/HackStudio/Makefile @@ -2,6 +2,7 @@ include ../../Makefile.common OBJS = \ Project.o \ + TerminalWrapper.o \ main.o APP = HackStudio @@ -11,7 +12,7 @@ DEFINES += -DUSERLAND all: $(APP) $(APP): $(OBJS) - $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -ldraw -lcore -lc + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lvt -lgui -ldraw -lcore -lc .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/DevTools/HackStudio/TerminalWrapper.cpp b/DevTools/HackStudio/TerminalWrapper.cpp new file mode 100644 index 0000000000..d1f20bf8bb --- /dev/null +++ b/DevTools/HackStudio/TerminalWrapper.cpp @@ -0,0 +1,95 @@ +#include "TerminalWrapper.h" +#include <AK/String.h> +#include <LibCore/CConfigFile.h> +#include <LibGUI/GBoxLayout.h> +#include <LibVT/TerminalWidget.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <unistd.h> + +static void run_command(int ptm_fd, const String& command) +{ + pid_t pid = fork(); + if (pid == 0) { + const char* tty_name = ptsname(ptm_fd); + if (!tty_name) { + perror("ptsname"); + exit(1); + } + close(ptm_fd); + int pts_fd = open(tty_name, O_RDWR); + if (pts_fd < 0) { + perror("open"); + exit(1); + } + + // NOTE: It's okay if this fails. + (void)ioctl(0, TIOCNOTTY); + + close(0); + close(1); + close(2); + + int rc = dup2(pts_fd, 0); + if (rc < 0) { + perror("dup2"); + exit(1); + } + rc = dup2(pts_fd, 1); + if (rc < 0) { + perror("dup2"); + exit(1); + } + rc = dup2(pts_fd, 2); + if (rc < 0) { + perror("dup2"); + exit(1); + } + rc = close(pts_fd); + if (rc < 0) { + perror("close"); + exit(1); + } + rc = ioctl(0, TIOCSCTTY); + if (rc < 0) { + perror("ioctl(TIOCSCTTY)"); + exit(1); + } + const char* args[4] = { "/bin/Shell", nullptr, nullptr, nullptr }; + if (!command.is_empty()) { + args[1] = "-c"; + args[2] = command.characters(); + } + const char* envs[] = { "TERM=xterm", "PATH=/bin:/usr/bin:/usr/local/bin", nullptr }; + rc = execve("/bin/Shell", const_cast<char**>(args), const_cast<char**>(envs)); + if (rc < 0) { + perror("execve"); + exit(1); + } + ASSERT_NOT_REACHED(); + } +} + +TerminalWrapper::TerminalWrapper(GWidget* parent) + : GWidget(parent) +{ + set_layout(make<GBoxLayout>(Orientation::Vertical)); + + int ptm_fd = open("/dev/ptmx", O_RDWR); + if (ptm_fd < 0) { + perror("open(ptmx)"); + ASSERT_NOT_REACHED(); + } + + run_command(ptm_fd, "/bin/Shell"); + + RefPtr<CConfigFile> config = CConfigFile::get_for_app("Terminal"); + m_terminal_widget = TerminalWidget::construct(ptm_fd, config); + add_child(*m_terminal_widget); +} + +TerminalWrapper::~TerminalWrapper() +{ +} diff --git a/DevTools/HackStudio/TerminalWrapper.h b/DevTools/HackStudio/TerminalWrapper.h new file mode 100644 index 0000000000..c36e421a1f --- /dev/null +++ b/DevTools/HackStudio/TerminalWrapper.h @@ -0,0 +1,16 @@ +#pragma once + +#include <LibGUI/GWidget.h> + +class TerminalWidget; + +class TerminalWrapper final : public GWidget { + C_OBJECT(TerminalWrapper) +public: + virtual ~TerminalWrapper() override; + +private: + explicit TerminalWrapper(GWidget* parent); + + RefPtr<TerminalWidget> m_terminal_widget; +}; diff --git a/DevTools/HackStudio/main.cpp b/DevTools/HackStudio/main.cpp index 8f14f07a4f..9142021493 100644 --- a/DevTools/HackStudio/main.cpp +++ b/DevTools/HackStudio/main.cpp @@ -1,4 +1,5 @@ #include "Project.h" +#include "TerminalWrapper.h" #include <LibCore/CFile.h> #include <LibGUI/GAction.h> #include <LibGUI/GApplication.h> @@ -39,13 +40,14 @@ int main(int argc, char** argv) auto toolbar = GToolBar::construct(widget); - auto splitter = GSplitter::construct(Orientation::Horizontal, widget); - auto project_list_view = GListView::construct(splitter); + auto outer_splitter = GSplitter::construct(Orientation::Horizontal, widget); + auto project_list_view = GListView::construct(outer_splitter); project_list_view->set_model(project->model()); project_list_view->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); project_list_view->set_preferred_size(200, 0); - auto text_editor = GTextEditor::construct(GTextEditor::MultiLine, splitter); + auto inner_splitter = GSplitter::construct(Orientation::Vertical, outer_splitter); + auto text_editor = GTextEditor::construct(GTextEditor::MultiLine, inner_splitter); text_editor->set_ruler_visible(true); project_list_view->on_activation = [&](auto& index) { @@ -58,6 +60,8 @@ int main(int argc, char** argv) text_editor->set_text(file->read_all()); }; + auto terminal_wrapper = TerminalWrapper::construct(inner_splitter); + auto statusbar = GStatusBar::construct(widget); text_editor->on_cursor_change = [&] { |