Start C++ rewrite.

This commit is contained in:
2025-11-24 23:36:19 -08:00
parent 7245003769
commit bbb23916a0
10 changed files with 758 additions and 97 deletions

View File

@@ -1,30 +1,64 @@
# CMake configuration for Kyle's Editor (ke)
cmake_minimum_required(VERSION 3.15)
project(ke C) # Specify C language explicitly
project(ke VERSION 1.3.3 LANGUAGES CXX)
set(CMAKE_C_STANDARD 99)
# Project metadata
set(KE_VERSION "1.3.3")
set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -Wshadow -Werror -std=c99 -g")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEFAULT_SOURCE -D_XOPEN_SOURCE")
# C++17 standard requirement
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Optionally enable AddressSanitizer (ASan)
# Source files
set(KE_SOURCES
main.cc
abuf.cc
erow.cc
)
# Header files
set(KE_HEADERS
ke_constants.h
abuf.h
erow.h
)
# Build options
option(ENABLE_ASAN "Enable AddressSanitizer for builds" OFF)
# Create executable target
add_executable(ke ${KE_SOURCES})
# Target compile features
target_compile_features(ke PRIVATE cxx_std_17)
# Target compile options
target_compile_options(ke PRIVATE
-Wall
-Wextra
-pedantic
-Wshadow
-Werror
-g
)
# Target compile definitions
target_compile_definitions(ke PRIVATE
KE_VERSION="ke version ${KE_VERSION}"
_DEFAULT_SOURCE
_XOPEN_SOURCE
)
# AddressSanitizer support
if(ENABLE_ASAN)
message(STATUS "ASan enabled")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
# Ensure the sanitizer is linked too (especially important on some platforms)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
target_compile_options(ke PRIVATE -fsanitize=address -fno-omit-frame-pointer)
target_link_options(ke PRIVATE -fsanitize=address)
endif()
# Installation rules
include(GNUInstallDirs)
# Add executable
add_executable(ke main.c)
target_compile_definitions(ke PRIVATE KE_VERSION="ke version ${KE_VERSION}")
install(TARGETS ke RUNTIME DESTINATION bin)
install(FILES ke.1 TYPE MAN)
install(TARGETS ke RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ke.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)

View File

@@ -2,17 +2,38 @@ TARGET := ke
KE_VERSION := devel
DEST := $(HOME)/.local/bin/$(TARGET)
CC := gcc
CXX := g++
CFLAGS := -Wall -Wextra -pedantic -Wshadow -Werror -std=c99 -g
CFLAGS += -Wno-unused-result
CFLAGS += -D_DEFAULT_SOURCE -D_XOPEN_SOURCE
CFLAGS += -fsanitize=address -fno-omit-frame-pointer
CXXFLAGS := -Wall -Wextra -pedantic -Wshadow -Werror -std=c++17 -g
CXXFLAGS += -Wno-unused-result
CXXFLAGS += -D_DEFAULT_SOURCE -D_XOPEN_SOURCE
CXXFLAGS += -DKE_VERSION='"ke $(KE_VERSION)"'
CXXFLAGS += -fsanitize=address -fno-omit-frame-pointer
LDFLAGS := -fsanitize=address
SOURCES := main.cc abuf.cc erow.cc
OBJECTS := main.o abuf.o erow.o
all: $(TARGET) test.txt
$(TARGET): main.c
$(CC) $(CFLAGS) -o $(TARGET) $(LDFLAGS) main.c
$(TARGET): $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJECTS) $(LDFLAGS)
main.o: main.cc ke_constants.h
$(CXX) $(CXXFLAGS) -c main.cc
abuf.o: abuf.cc abuf.h
$(CXX) $(CXXFLAGS) -c abuf.cc
erow.o: erow.cc erow.h
$(CXX) $(CXXFLAGS) -c erow.cc
.PHONY: install
#install: $(TARGET)
@@ -21,6 +42,7 @@ install:
clean:
rm -f $(TARGET)
rm -f $(OBJECTS)
rm -f asan.log*
.PHONY: test.txt

17
abuf.cc Normal file
View File

@@ -0,0 +1,17 @@
#include "abuf.h"
namespace ke {
void abuf::append(std::string_view s) {
buffer_.append(s);
}
void abuf::append(const char* s, std::size_t len) {
buffer_.append(s, len);
}
void abuf::append(char c) {
buffer_.push_back(c);
}
} // namespace ke

57
abuf.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef ABUF_HPP
#define ABUF_HPP
#include <string>
#include <string_view>
#include <cstddef>
namespace ke {
/**
* Append buffer class for efficient string building.
* C++17 implementation with RAII memory management.
*/
class abuf {
public:
// Constructors
abuf() noexcept = default;
// Deleted copy constructor and assignment (use move semantics)
abuf(const abuf&) = delete;
abuf& operator=(const abuf&) = delete;
// Move constructor and assignment
abuf(abuf&&) noexcept = default;
abuf& operator=(abuf&&) noexcept = default;
// Destructor (automatic cleanup via std::string)
~abuf() = default;
// Append methods
void append(std::string_view s);
void append(const char* s, std::size_t len);
void append(char c);
// Accessors
[[nodiscard]] const char* data() const noexcept { return buffer_.data(); }
[[nodiscard]] std::size_t size() const noexcept { return buffer_.size(); }
[[nodiscard]] std::size_t length() const noexcept { return buffer_.length(); }
[[nodiscard]] bool empty() const noexcept { return buffer_.empty(); }
[[nodiscard]] std::size_t capacity() const noexcept { return buffer_.capacity(); }
// Get the underlying string
[[nodiscard]] const std::string& str() const noexcept { return buffer_; }
// Clear the buffer
void clear() noexcept { buffer_.clear(); }
// Reserve capacity
void reserve(std::size_t new_cap) { buffer_.reserve(new_cap); }
private:
std::string buffer_;
};
} // namespace ke
#endif // ABUF_HPP

View File

@@ -0,0 +1,115 @@
# Constants Refactoring Documentation
## Overview
This document describes the refactoring of #defines and common constants into a single centralized header file for Kyle's Editor (ke).
## Changes Made
### 1. Created `ke_constants.h`
A new header file was created to centralize all common constants and preprocessor definitions used throughout the project.
**Location**: `/Users/kyle/src/ke2/ke_constants.h`
**Contents**:
- **Version Information**: `KE_VERSION` - Editor version string
- **Terminal Sequences**: `ESCSEQ` - ANSI escape sequence prefix
- **Keyboard Macros**: `CTRL_KEY(key)` - Control key combination macro
- **Display Constants**:
- `TAB_STOP` (8) - Tab stop width
- `MSG_TIMEO` (3) - Message timeout in seconds
- **Memory Management**: `INITIAL_CAPACITY` (64) - Initial buffer capacity
- **Keyboard Modes**:
- `MODE_NORMAL` (0) - Normal editing mode
- `MODE_KCOMMAND` (1) - Command mode (^k commands)
- `MODE_ESCAPE` (2) - Escape key handling mode
- **Kill Ring Operations**:
- `KILLRING_NO_OP` (0) - No operation
- `KILLRING_APPEND` (1) - Append deleted characters
- `KILLRING_PREPEND` (2) - Prepend deleted characters
- `KILLING_SET` (3) - Set killring to deleted character
- `KILLRING_FLUSH` (4) - Clear the killring
- **Legacy Initializers**: `ABUF_INIT` - C struct initializer for append buffer
### 2. Updated `main.c`
- Added `#include "ke_constants.h"` at the top with other includes
- Removed all duplicate #define statements that were moved to the constants header
- Eliminated the duplicate `TAB_STOP` definition (was defined twice on lines 36 and 50)
- Cleaned up approximately 30+ lines of redundant definitions
### 3. Updated `erow.cpp`
- Added `#include "ke_constants.h"` with extern "C" linkage for C++ compatibility
- Removed local `constexpr int TAB_STOP = 8` definition
- Now uses the centralized `TAB_STOP` constant from `ke_constants.h`
## Benefits
1. **Single Source of Truth**: All constants are now defined in one location, making them easier to maintain and modify
2. **Eliminated Duplication**: Removed duplicate definitions (e.g., TAB_STOP was defined twice in main.c)
3. **Better Organization**: Constants are grouped logically by category with clear comments
4. **Cross-Language Compatibility**: Header works with both C (main.c) and C++ (erow.cpp) code
5. **Easier Maintenance**: Future changes to constants only need to be made in one place
6. **Improved Readability**: Cleaner source files with less clutter from #define statements
## Build System Compatibility
Both build systems have been tested and verified to work correctly:
### Makefile Build
```bash
make clean
make
```
Successfully compiles all files (main.c, abuf.cpp, erow.cpp) and links the executable.
### CMake Build
```bash
cd cmake-build-debug
cmake --build . --clean-first
```
Successfully builds the project with all components.
## Header Guard
The header uses standard include guards:
```c
#ifndef KE_CONSTANTS_H
#define KE_CONSTANTS_H
...
#endif /* KE_CONSTANTS_H */
```
## C/C++ Interoperability
When including in C++ files, use extern "C" linkage:
```cpp
extern "C" {
#include "ke_constants.h"
}
```
This ensures proper linkage and prevents name mangling issues.
## Future Considerations
1. **Additional Constants**: As the project grows, any new constants should be added to `ke_constants.h` rather than being scattered across source files
2. **Namespacing**: For C++ constants, consider creating a dedicated C++ header with namespaced constants
3. **Type Safety**: For C++ code, consider using `constexpr` or `inline constexpr` variables in a C++ header for better type safety
4. **Documentation**: Keep this document updated as new constants are added or modified
## Testing
All compilation tests passed:
- ✅ Makefile build: Clean compilation with no errors or warnings
- ✅ CMake build: Clean compilation with no errors or warnings
- ✅ All source files (C and C++) successfully include and use the constants
- ✅ No duplicate definition errors
- ✅ Proper linkage between C and C++ components
## Related Files
- `ke_constants.h` - The new constants header (created)
- `main.c` - Updated to use new header (modified)
- `erow.cpp` - Updated to use new header (modified)
- `Makefile` - No changes required (working)
- `CMakeLists.txt` - No changes required (working)
## Date
November 24, 2025

109
docs/CPP17_CONVERSION.md Normal file
View File

@@ -0,0 +1,109 @@
# C++17 Conversion Documentation
## Overview
This document describes the initial conversion of the ke2 project from C to C++17 standards, starting with the `abuf` and `erow` structures as requested.
## Converted Components
### 1. abuf (Append Buffer)
**Original C Structure (main.c:69-73):**
```c
struct abuf {
char *b;
int len;
int cap;
};
```
**C++17 Implementation (abuf.hpp, abuf.cpp):**
- Converted to a modern C++ class using RAII principles
- Uses `std::string` as the internal buffer for automatic memory management
- Implements move semantics (deleted copy operations)
- Uses C++17 features:
- `std::string_view` for efficient string parameters
- `[[nodiscard]]` attributes for better safety
- `noexcept` specifications where appropriate
- No manual memory management required - destructor automatically handled by std::string
**Key Improvements:**
- Automatic memory cleanup (RAII)
- Exception-safe
- No memory leaks possible
- More efficient with move semantics
- Type-safe with modern C++ idioms
### 2. erow (Editor Row)
**Original C Structure (main.c:79-87):**
```c
struct erow {
char *line;
char *render;
int size;
int rsize;
int cap;
};
```
**C++17 Implementation (erow.hpp, erow.cpp):**
- Converted to a C++ class with proper encapsulation
- Uses `std::string` for both `line` and `render` buffers
- Implements move semantics (deleted copy operations)
- All manual memory management replaced with RAII
- Retains all original functionality:
- UTF-8 character handling with `mbrtowc` and `wcwidth`
- Tab expansion (TAB_STOP = 8)
- Control character rendering as `\xx`
- Cursor-to-render and render-to-cursor position conversions
**Key Improvements:**
- Automatic memory cleanup for both line and render buffers
- No malloc/free/realloc needed
- Exception-safe operations
- Better encapsulation with private members
- Modern C++ method naming conventions
## Build System Updates
### Makefile
- Added C++ compiler support (g++)
- Added CXXFLAGS with `-std=c++17`
- Modified build rules to compile C and C++ separately
- Updated to link with C++ compiler
- Enhanced clean target to remove object files
### CMakeLists.txt
- Changed project language from `C` to `C CXX`
- Added `CMAKE_CXX_STANDARD 17` and `CMAKE_CXX_STANDARD_REQUIRED ON`
- Added C++ compiler flags matching C flags
- Updated executable target to include `abuf.cpp` and `erow.cpp`
- Maintained backward compatibility with existing C code (main.c)
## Compilation Testing
Both build systems have been tested and verified:
- ✅ Makefile: Successfully compiles with `make`
- ✅ CMake: Successfully configures and builds
- ✅ Object files generated correctly for all C++ sources
- ✅ No compilation warnings or errors
## C++17 Features Used
1. **std::string** - Modern string class with automatic memory management
2. **std::string_view** - Efficient non-owning string references (C++17)
3. **[[nodiscard]]** - Compiler warnings for ignored return values (C++17)
4. **noexcept** - Exception specifications for optimization
5. **default/delete** - Explicit control over special member functions
6. **Move semantics** - Efficient resource transfer
7. **constexpr** - Compile-time constants (TAB_STOP)
## Next Steps
The project now has a foundation for further C++17 conversion:
- Additional structures can be converted following the same patterns
- Consider converting more C code to C++ classes
- Potential for using more STL containers (std::vector for dynamic arrays)
- Opportunity to use smart pointers for other memory management
- Can leverage more C++17 features (std::optional, structured bindings, etc.)
## Compatibility
- The new C++ code coexists with existing C code (main.c)
- Both can be compiled together and linked successfully
- The conversion maintains the original functionality
- No changes required to existing C code at this stage

214
erow.cc Normal file
View File

@@ -0,0 +1,214 @@
#include "erow.h"
#include <cstring>
#include <cwchar>
#include <cassert>
#include "ke_constants.h"
namespace ke {
// Constructors
erow::erow(std::size_t initial_capacity) {
line_.reserve(initial_capacity);
}
erow::erow(const char* text, std::size_t len) {
line_.assign(text, len);
}
// Set line content
void erow::set_line(const char* data, std::size_t len) {
line_.assign(data, len);
}
// Append string to the line
void erow::append_string(const char* s, std::size_t len) {
line_.append(s, len);
}
// Insert character at position
void erow::insert_char(std::size_t at, char c) {
if (at > line_.size()) {
at = line_.size();
}
line_.insert(at, 1, c);
}
// Delete character at position
void erow::delete_char(std::size_t at) {
if (at < line_.size()) {
line_.erase(at, 1);
}
}
// Helper function for nibble to hex conversion
char erow::nibble_to_hex(char c) {
c &= 0xf;
if (c < 10) {
return static_cast<char>('0' + c);
}
return static_cast<char>('A' + (c - 10));
}
// Update the render string based on the line content
void erow::update() {
int tabs = 0;
int ctrl = 0;
// Count tabs and control characters
for (std::size_t j = 0; j < line_.size(); ++j) {
if (line_[j] == '\t') {
++tabs;
} else if (static_cast<unsigned char>(line_[j]) < 0x20) {
++ctrl;
}
}
// Allocate render buffer
render_.clear();
render_.reserve(line_.size() + (tabs * (TAB_STOP - 1)) + (ctrl * 3) + 1);
// Build the render string
for (std::size_t j = 0; j < line_.size(); ++j) {
if (line_[j] == '\t') {
// Expand tabs to spaces
do {
render_.push_back(' ');
} while ((render_.size() % TAB_STOP) != 0);
} else if (static_cast<unsigned char>(line_[j]) < 0x20) {
// Render control characters as \xx
render_.push_back('\\');
render_.push_back(nibble_to_hex(line_[j] >> 4));
render_.push_back(nibble_to_hex(line_[j] & 0x0f));
} else {
// Leave UTF-8 multibyte bytes untouched
render_.push_back(line_[j]);
}
}
}
// Convert cursor position to render position
int erow::render_to_cursor(int cx) const {
int rx = 0;
std::size_t j = 0;
wchar_t wc;
std::mbstate_t st{};
while (j < static_cast<std::size_t>(cx) && j < line_.size()) {
unsigned char b = static_cast<unsigned char>(line_[j]);
if (b == '\t') {
rx += (TAB_STOP - 1) - (rx % TAB_STOP);
++rx;
++j;
continue;
}
if (b < 0x20) {
// Render as \xx -> width 3
rx += 3;
++j;
continue;
}
std::size_t rem = line_.size() - j;
std::size_t n = std::mbrtowc(&wc, &line_[j], rem, &st);
if (n == static_cast<std::size_t>(-2)) {
// Incomplete sequence at end; treat one byte
rx += 1;
j += 1;
std::memset(&st, 0, sizeof(st));
} else if (n == static_cast<std::size_t>(-1)) {
// Invalid byte; consume one and reset state
rx += 1;
j += 1;
std::memset(&st, 0, sizeof(st));
} else if (n == 0) {
// Null character
rx += 0;
j += 1;
} else {
int w = wcwidth(wc);
if (w < 0) {
w = 1; // Non-printable -> treat as width 1
}
rx += w;
j += n;
}
}
return rx;
}
// Convert render position to cursor position
int erow::cursor_to_render(int rx) const {
int cur_rx = 0;
std::size_t j = 0;
wchar_t wc;
std::mbstate_t st{};
while (j < line_.size()) {
unsigned char b = static_cast<unsigned char>(line_[j]);
if (b == '\t') {
int tab_width = (TAB_STOP - 1) - (cur_rx % TAB_STOP) + 1;
if (cur_rx + tab_width > rx) {
break;
}
cur_rx += tab_width;
++j;
continue;
}
if (b < 0x20) {
// Control char width is 3
if (cur_rx + 3 > rx) {
break;
}
cur_rx += 3;
++j;
continue;
}
std::size_t rem = line_.size() - j;
std::size_t n = std::mbrtowc(&wc, &line_[j], rem, &st);
std::size_t adv = 1;
int w = 1;
if (n == static_cast<std::size_t>(-2)) {
// Incomplete sequence
adv = 1;
w = 1;
std::memset(&st, 0, sizeof(st));
} else if (n == static_cast<std::size_t>(-1)) {
// Invalid byte
adv = 1;
w = 1;
std::memset(&st, 0, sizeof(st));
} else if (n == 0) {
// Null character
adv = 1;
w = 0;
} else {
adv = n;
w = wcwidth(wc);
if (w < 0) {
w = 1;
}
}
if (cur_rx + w > rx) {
break;
}
cur_rx += w;
j += adv;
}
return static_cast<int>(j);
}
} // namespace ke

76
erow.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef EROW_HPP
#define EROW_HPP
#include <string>
#include <memory>
#include <cstddef>
#include <cstdint>
namespace ke {
/**
* Editor row class representing a line of text with rendering information.
* C++17 implementation with RAII memory management.
*/
class erow {
public:
// Constructors
erow() noexcept = default;
explicit erow(std::size_t initial_capacity);
erow(const char* text, std::size_t len);
// Deleted copy constructor and assignment (use move semantics)
erow(const erow&) = delete;
erow& operator=(const erow&) = delete;
// Move constructor and assignment
erow(erow&&) noexcept = default;
erow& operator=(erow&&) noexcept = default;
// Destructor (automatic cleanup via std::string)
~erow() = default;
// Core operations
void update();
void insert_char(std::size_t at, char c);
void delete_char(std::size_t at);
void append_string(const char* s, std::size_t len);
// Cursor/render position conversions
[[nodiscard]] int render_to_cursor(int cx) const;
[[nodiscard]] int cursor_to_render(int rx) const;
// Accessors for line data
[[nodiscard]] const char* line_data() const noexcept { return line_.data(); }
[[nodiscard]] char* line_data() noexcept { return line_.data(); }
[[nodiscard]] std::size_t line_size() const noexcept { return line_.size(); }
[[nodiscard]] std::size_t line_capacity() const noexcept { return line_.capacity(); }
// Accessors for render data
[[nodiscard]] const char* render_data() const noexcept { return render_.data(); }
[[nodiscard]] std::size_t render_size() const noexcept { return render_.size(); }
// Direct access to strings (for compatibility)
[[nodiscard]] std::string& line() noexcept { return line_; }
[[nodiscard]] const std::string& line() const noexcept { return line_; }
[[nodiscard]] const std::string& render() const noexcept { return render_; }
// Resize operations
void resize_line(std::size_t new_size) { line_.resize(new_size); }
void reserve_line(std::size_t new_cap) { line_.reserve(new_cap); }
// Set line content
void set_line(const char* data, std::size_t len);
void set_line(std::string&& data) noexcept { line_ = std::move(data); }
private:
std::string line_; // The actual line content
std::string render_; // The rendered version (with tabs expanded, etc.)
// Helper for nibble to hex conversion
static char nibble_to_hex(char c);
};
} // namespace ke
#endif // EROW_HPP

44
ke_constants.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* ke_constants.h
*
* Common constants and defines for Kyle's Editor (ke)
* Refactored from main.c and other source files for centralized maintenance.
*/
#ifndef KE_CONSTANTS_H
#define KE_CONSTANTS_H
/* Version information */
#ifndef KE_VERSION
#define KE_VERSION "ke dev build"
#endif
/* Terminal escape sequences */
#define ESCSEQ "\x1b["
/* Keyboard and control key macros */
#define CTRL_KEY(key) ((key)&0x1f)
/* Display and rendering constants */
#define TAB_STOP 8
#define MSG_TIMEO 3
/* Memory management constants */
#define INITIAL_CAPACITY 64
/* Keyboard input modes */
#define MODE_NORMAL 0
#define MODE_KCOMMAND 1
#define MODE_ESCAPE 2
/* Kill ring operations */
#define KILLRING_NO_OP 0 /* don't touch the killring */
#define KILLRING_APPEND 1 /* append deleted chars */
#define KILLRING_PREPEND 2 /* prepend deleted chars */
#define KILLING_SET 3 /* set killring to deleted char */
#define KILLRING_FLUSH 4 /* clear the killring */
/* Legacy C struct initializers (for compatibility with main.c) */
#define ABUF_INIT {NULL, 0, 0}
#endif /* KE_CONSTANTS_H */

View File

@@ -9,55 +9,24 @@
* https://viewsourcecode.org/snaptoken/kilo/
*/
#include <sys/ioctl.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <cassert>
#include <cctype>
#include <cerrno>
#include <cstdarg>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <clocale>
#include <cwchar>
#include <ctime>
#ifndef KE_VERSION
#define KE_VERSION "ke dev build"
#endif
#define ESCSEQ "\x1b["
#define CTRL_KEY(key) ((key)&0x1f)
#define TAB_STOP 8
#define MSG_TIMEO 3
/*
* define the keyboard input modes
* normal: no special mode
* kcommand: ^k commands
* escape: what happens when you hit escape?
*/
#define MODE_NORMAL 0
#define MODE_KCOMMAND 1
#define MODE_ESCAPE 2
#define TAB_STOP 8
#define INITIAL_CAPACITY 64
#define KILLRING_NO_OP 0 /* don't touch the killring */
#define KILLRING_APPEND 1 /* append deleted chars */
#define KILLRING_PREPEND 2 /* prepend deleted chars */
#define KILLING_SET 3 /* set killring to deleted char */
#define KILLRING_FLUSH 4 /* clear the killring */
#include "ke_constants.h"
@@ -144,7 +113,7 @@ int erow_render_to_cursor(struct erow *row, int cx);
int erow_cursor_to_render(struct erow *row, int rx);
int erow_init(struct erow *row, int len);
void erow_update(struct erow *row);
void erow_insert(int at, char *s, int len);
void erow_insert(int at, const char *s, int len);
void erow_free(struct erow *row);
/* kill ring, marking, etc */
@@ -175,7 +144,7 @@ int16_t get_keypress(void);
void display_refresh(void);
void editor_find_callback(char *query, int16_t c);
void editor_find(void);
char *editor_prompt(char *, void (*cb)(char *, int16_t));
char *editor_prompt(const char *, void (*cb)(char *, int16_t));
void editor_openfile(void);
void move_cursor(int16_t c);
void newline(void);
@@ -321,7 +290,7 @@ ab_append(struct abuf *buf, const char *s, int len)
buf->cap *= 2;
}
}
nc = realloc(nc, buf->cap);
nc = static_cast<char*>(realloc(nc, buf->cap));
assert(nc != NULL);
}
@@ -483,7 +452,7 @@ erow_init(struct erow *row, int len)
row->line = NULL;
row->cap = cap_growth(0, len)+1; /* extra byte for NUL end */
row->line = malloc(row->cap);
row->line = static_cast<char*>(malloc(row->cap));
assert(row->line != NULL);
if (row->line == NULL) {
return -1;
@@ -518,8 +487,8 @@ erow_update(struct erow *row)
row->rsize = 0;
}
row->render = NULL;
row->render = malloc(
row->size + (tabs * (TAB_STOP - 1)) + (ctrl * 3) + 1);
row->render = static_cast<char*>(malloc(
row->size + (tabs * (TAB_STOP - 1)) + (ctrl * 3) + 1));
assert(row->render != NULL);
for (j = 0; j < row->size; j++) {
@@ -543,7 +512,7 @@ erow_update(struct erow *row)
void
erow_insert(int at, char *s, int len)
erow_insert(int at, const char *s, int len)
{
struct erow row;
@@ -555,8 +524,8 @@ erow_insert(int at, char *s, int len)
memcpy(row.line, s, len);
row.line[len] = 0;
editor.row = realloc(editor.row,
sizeof(struct erow) * (editor.nrows + 1));
editor.row = static_cast<struct erow*>(realloc(editor.row,
sizeof(struct erow) * (editor.nrows + 1)));
assert(editor.row != NULL);
if (at < editor.nrows) {
@@ -625,14 +594,14 @@ killring_start_with_char(unsigned char ch)
editor.killring = NULL;
}
editor.killring = malloc(sizeof(struct erow));
editor.killring = static_cast<struct erow*>(malloc(sizeof(struct erow)));
assert(editor.killring != NULL);
assert(erow_init(editor.killring, 0) == 0);
/* append one char to empty killring without affecting editor.dirty */
row = editor.killring;
row->line = realloc(row->line, row->size + 2);
row->line = static_cast<char*>(realloc(row->line, row->size + 2));
assert(row->line != NULL);
row->line[row->size] = ch;
row->size++;
@@ -652,7 +621,7 @@ killring_append_char(unsigned char ch)
}
row = editor.killring;
row->line = realloc(row->line, row->size + 2);
row->line = static_cast<char*>(realloc(row->line, row->size + 2));
assert(row->line != NULL);
row->line[row->size] = ch;
row->size++;
@@ -670,7 +639,7 @@ killring_prepend_char(unsigned char ch)
}
struct erow *row = editor.killring;
row->line = realloc(row->line, row->size + 2);
row->line = static_cast<char*>(realloc(row->line, row->size + 2));
assert(row->line != NULL);
memmove(&row->line[1], &row->line[0], row->size + 1);
row->line[0] = ch;
@@ -1058,7 +1027,7 @@ delete_row(int at)
void
row_append_row(struct erow *row, char *s, int len)
{
row->line = realloc(row->line, row->size + len + 1);
row->line = static_cast<char*>(realloc(row->line, row->size + len + 1));
assert(row->line != NULL);
memcpy(&row->line[row->size], s, len);
row->size += len;
@@ -1079,7 +1048,7 @@ row_insert_ch(struct erow *row, int at, int16_t c)
}
assert(c > 0);
row->line = realloc(row->line, row->size + 2);
row->line = static_cast<char*>(realloc(row->line, row->size + 2));
assert(row->line != NULL);
memmove(&row->line[at + 1], &row->line[at], row->size - at + 1);
row->size++;
@@ -1255,7 +1224,7 @@ rows_to_buffer(int *buflen)
}
*buflen = len;
buf = malloc(len);
buf = static_cast<char*>(malloc(len));
assert(buf != NULL);
p = buf;
@@ -1437,10 +1406,10 @@ get_keypress(void)
char *
editor_prompt(char *prompt, void (*cb)(char *, int16_t))
editor_prompt(const char *prompt, void (*cb)(char *, int16_t))
{
size_t bufsz = 128;
char *buf = malloc(bufsz);
char *buf = static_cast<char*>(malloc(bufsz));
size_t buflen = 0;
int16_t c;
@@ -1472,7 +1441,7 @@ editor_prompt(char *prompt, void (*cb)(char *, int16_t))
} else if ((c == TAB_KEY) || (c >= 0x20 && c != 0x7f)) {
if (buflen == bufsz - 1) {
bufsz *= 2;
buf = realloc(buf, bufsz);
buf = static_cast<char*>(realloc(buf, bufsz));
assert(buf != NULL);
}
@@ -1724,7 +1693,7 @@ get_cloc_code_lines(const char* filename)
if (editor.filename == NULL) {
snprintf(command, sizeof(command),
"buffer has no associated file.");
result = malloc((strnlen(command, sizeof(command))) + 1);
result = static_cast<char*>(malloc((strnlen(command, sizeof(command))) + 1));
assert(result != NULL);
strcpy(result, command);
return result;
@@ -1733,7 +1702,7 @@ get_cloc_code_lines(const char* filename)
if (editor.dirty) {
snprintf(command, sizeof(command),
"buffer must be saved first.");
result = malloc((strnlen(command, sizeof(command))) + 1);
result = static_cast<char*>(malloc((strnlen(command, sizeof(command))) + 1));
assert(result != NULL);
strcpy(result, command);
return result;
@@ -1747,7 +1716,7 @@ get_cloc_code_lines(const char* filename)
pipe = popen(command, "r");
if (!pipe) {
snprintf(command, sizeof(command), "Error getting LOC: %s", strerror(errno));
result = (char *)malloc(sizeof(buffer) + 1);
result = static_cast<char*>(malloc(sizeof(buffer) + 1));
return NULL;
}
@@ -1757,7 +1726,7 @@ get_cloc_code_lines(const char* filename)
buffer[len - 1] = '\0';
}
result = malloc(strlen(buffer) + 1);
result = static_cast<char*>(malloc(strlen(buffer) + 1));
assert(result != NULL);
if (result) {
strcpy(result, buffer);
@@ -1767,7 +1736,7 @@ get_cloc_code_lines(const char* filename)
}
pclose(pipe);
char *zero = malloc(2);
char *zero = static_cast<char*>(malloc(2));
if (zero) {
strcpy(zero, "0");
return zero;
@@ -2088,7 +2057,7 @@ draw_rows(struct abuf *ab)
{
assert(editor.cols >= 0);
char buf[editor.cols];
char *buf = new char[editor.cols];
int buflen, filerow, padding;
int y;
@@ -2097,7 +2066,7 @@ draw_rows(struct abuf *ab)
if (filerow >= editor.nrows) {
if ((editor.nrows == 0) && (y == editor.rows / 3)) {
buflen = snprintf(buf,
sizeof(buf),
editor.cols,
"%s",
KE_VERSION);
padding = (editor.rows - buflen) / 2;
@@ -2130,6 +2099,7 @@ draw_rows(struct abuf *ab)
ab_append(ab, ESCSEQ "K", 3);
ab_append(ab, "\r\n", 2);
}
delete[] buf;
}
@@ -2152,14 +2122,14 @@ status_mode_char(void)
void
draw_status_bar(struct abuf *ab)
{
char status[editor.cols];
char rstatus[editor.cols];
char mstatus[editor.cols];
char *status = new char[editor.cols];
char *rstatus = new char[editor.cols];
char *mstatus = new char[editor.cols];
int len, rlen;
len = snprintf(status,
sizeof(status),
editor.cols,
"%c%cke: %.20s - %d lines",
status_mode_char(),
editor.dirty ? '!' : '-',
@@ -2168,16 +2138,16 @@ draw_status_bar(struct abuf *ab)
if (editor.mark_set) {
snprintf(mstatus,
sizeof(mstatus),
editor.cols,
" | M: %d, %d ",
editor.mark_curx + 1,
editor.mark_cury + 1);
} else {
snprintf(mstatus, sizeof(mstatus), " | M:clear ");
snprintf(mstatus, editor.cols, " | M:clear ");
}
rlen = snprintf(rstatus,
sizeof(rstatus),
editor.cols,
"L%d/%d C%d %s",
editor.cury + 1,
editor.nrows,
@@ -2196,6 +2166,9 @@ draw_status_bar(struct abuf *ab)
}
ab_append(ab, ESCSEQ "m", 3);
ab_append(ab, "\r\n", 2);
delete[] status;
delete[] rstatus;
delete[] mstatus;
}