mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-10 17:02:56 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c43e85141 | ||
|
|
9da42c18c3 | ||
|
|
d115c7f6aa | ||
|
|
2efce0fd83 | ||
|
|
f6732133e7 |
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
bsnes (TM) Open Source Reference License
|
||||
bsnes (TM) Reference License
|
||||
Copyright (C) 2004 - 2007 byuu
|
||||
All rights reserved
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
bsnes
|
||||
Version 0.026
|
||||
Version 0.027
|
||||
Author: byuu
|
||||
|
||||
--------
|
||||
|
||||
+333
-321
@@ -1,321 +1,333 @@
|
||||
######################
|
||||
### bsnes makefile ###
|
||||
######################
|
||||
|
||||
ifeq ($(PLATFORM),)
|
||||
_null_: help
|
||||
endif
|
||||
|
||||
##################################
|
||||
### platform-specific settings ###
|
||||
##################################
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-lui)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
AS = nasm
|
||||
ASFLAGS = -f elf
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_gtk
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-lui-x64)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_LUI `pkg-config --cflags gtk+-2.0`
|
||||
AS = yasm
|
||||
ASFLAGS = -f elf64
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco_x86_64
|
||||
LIBUI = libui_gtk
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-lui)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-lui-pgi)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-lui-pgo)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-mingw-lui)
|
||||
OS = win
|
||||
CC = mingw32-gcc
|
||||
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
#####################################
|
||||
### compiler / assembler switches ###
|
||||
#####################################
|
||||
|
||||
ifeq ($(CC),gcc)
|
||||
OUT = -obsnes
|
||||
CPP = g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OUT = -obsnes
|
||||
CPP = mingw32-g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),cl)
|
||||
OUT = /Febsnes
|
||||
CPP = cl
|
||||
OBJ = obj
|
||||
CARGS = /c $< /Fo$@
|
||||
DEFINE = /D
|
||||
endif
|
||||
|
||||
ifeq ($(AS),nasm)
|
||||
ASARGS = $< -o $@
|
||||
endif
|
||||
|
||||
ifeq ($(AS),yasm)
|
||||
ASARGS = $< -o $@
|
||||
endif
|
||||
|
||||
###################
|
||||
### OS switches ###
|
||||
###################
|
||||
|
||||
ifeq ($(OS),unix)
|
||||
RM = rm -f
|
||||
endif
|
||||
|
||||
ifeq ($(OS),win)
|
||||
OUT := $(OUT).exe
|
||||
RM = del
|
||||
endif
|
||||
|
||||
####################################
|
||||
### main target and dependencies ###
|
||||
####################################
|
||||
|
||||
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(LIBUI).$(OBJ) \
|
||||
libstring.$(OBJ) \
|
||||
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) smemory.$(OBJ) \
|
||||
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
|
||||
bppu.$(OBJ) snes.$(OBJ) bsx.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) \
|
||||
sdd1.$(OBJ) cx4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) \
|
||||
obc1.$(OBJ) st010.$(OBJ)
|
||||
|
||||
ifeq ($(GZIP_SUPPORT),true)
|
||||
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
|
||||
gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \
|
||||
trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ)
|
||||
CFLAGS += $(DEFINE)GZIP_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(JMA_SUPPORT),true)
|
||||
OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \
|
||||
iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
|
||||
CFLAGS += $(DEFINE)JMA_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(OS),win)
|
||||
ifeq ($(CC),cl)
|
||||
OBJECTS += bsnes.res
|
||||
endif
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OBJECTS += bsnesrc.o
|
||||
endif
|
||||
endif
|
||||
|
||||
all: $(OBJECTS)
|
||||
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
|
||||
|
||||
install:
|
||||
cp bsnes /usr/local/bin/bsnes
|
||||
cp data/bsnes.png /usr/local/share/icons/bsnes.png
|
||||
chmod 775 /usr/local/bin/bsnes /usr/local/share/icons/bsnes.png
|
||||
|
||||
######################
|
||||
### implicit rules ###
|
||||
######################
|
||||
|
||||
%.$(OBJ): $<
|
||||
$(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS))
|
||||
$(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS))
|
||||
$(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS))
|
||||
|
||||
#########################
|
||||
### platform-specific ###
|
||||
#########################
|
||||
main.$(OBJ): ui/main.cpp config/* ui/* ui/video/* ui/audio/* ui/input/* \
|
||||
ui/lui/* ui/lui/loader/* ui/lui/settings/* \
|
||||
ui/win/* ui/win/settings/* ui/win/debugger/*
|
||||
|
||||
bsnes.res: ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
|
||||
bsnesrc.o: ui/bsnes.rc ; windres -I data ui/bsnes.rc bsnesrc.o
|
||||
|
||||
#############
|
||||
### libco ###
|
||||
#############
|
||||
libco_x86.$(OBJ) : lib/libco_x86.asm lib/*
|
||||
libco_x86_64.$(OBJ): lib/libco_x86_64.asm lib/*
|
||||
|
||||
#############
|
||||
### libui ###
|
||||
#############
|
||||
libui_gtk.$(OBJ): lib/libui_gtk.cpp lib/*
|
||||
libui_win.$(OBJ): lib/libui_win.cpp lib/*
|
||||
|
||||
#################
|
||||
### libraries ###
|
||||
#################
|
||||
libstring.$(OBJ): lib/libstring.cpp lib/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
#################
|
||||
reader.$(OBJ): reader/reader.cpp reader/*
|
||||
cart.$(OBJ) : cart/cart.cpp cart/*
|
||||
cheat.$(OBJ) : cheat/cheat.cpp cheat/*
|
||||
|
||||
##############
|
||||
### memory ###
|
||||
##############
|
||||
memory.$(OBJ) : memory/memory.cpp memory/*
|
||||
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
|
||||
smemory.$(OBJ): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
|
||||
|
||||
###########
|
||||
### cpu ###
|
||||
###########
|
||||
cpu.$(OBJ) : cpu/cpu.cpp cpu/*
|
||||
scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
||||
|
||||
###########
|
||||
### smp ###
|
||||
###########
|
||||
smp.$(OBJ) : smp/smp.cpp smp/*
|
||||
ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
|
||||
|
||||
###########
|
||||
### dsp ###
|
||||
###########
|
||||
adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/*
|
||||
|
||||
###########
|
||||
### ppu ###
|
||||
###########
|
||||
ppu.$(OBJ) : ppu/ppu.cpp ppu/*
|
||||
bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
bsx.$(OBJ) : chip/bsx/bsx.cpp chip/bsx/*
|
||||
superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/*
|
||||
srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/*
|
||||
sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
cx4.$(OBJ) : chip/cx4/cx4.cpp chip/cx4/*
|
||||
dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
st010.$(OBJ) : chip/st010/st010.cpp chip/st010/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
############
|
||||
adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/*
|
||||
compress.$(OBJ): reader/zlib/compress.c reader/zlib/*
|
||||
crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/*
|
||||
deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/*
|
||||
gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/*
|
||||
inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/*
|
||||
inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/*
|
||||
inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/*
|
||||
ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/*
|
||||
trees.$(OBJ) : reader/zlib/trees.c reader/zlib/*
|
||||
unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/*
|
||||
zip.$(OBJ) : reader/zlib/zip.c reader/zlib/*
|
||||
zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/*
|
||||
|
||||
###########
|
||||
### jma ###
|
||||
###########
|
||||
jma.$(OBJ) : reader/jma/jma.cpp reader/jma/*
|
||||
jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/*
|
||||
lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/*
|
||||
7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/*
|
||||
iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/*
|
||||
inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/*
|
||||
lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/*
|
||||
winout.$(OBJ) : reader/jma/winout.cpp reader/jma/*
|
||||
|
||||
####################
|
||||
### misc targets ###
|
||||
####################
|
||||
clean:
|
||||
-@$(RM) *.$(OBJ)
|
||||
-@$(RM) *.res
|
||||
-@$(RM) *.pgd
|
||||
-@$(RM) *.pgc
|
||||
-@$(RM) *.ilk
|
||||
-@$(RM) *.pdb
|
||||
-@$(RM) *.manifest
|
||||
|
||||
help:
|
||||
@echo "Usage: $(MAKE) PLATFORM=platform [options]"
|
||||
@echo ""
|
||||
@echo "Available platform targets:"
|
||||
@echo " x-gcc-lui - Linux / BSD (i386) (requires nasm)"
|
||||
@echo " x-gcc-lui-x64 - Linux / BSD (amd64) (requires yasm)"
|
||||
@echo " win-mingw-lui - Windows (i386) (requires nasm)"
|
||||
@echo " win-visualc-lui - Windows (i386) (requires nasm)"
|
||||
@echo ""
|
||||
@echo "Available options:"
|
||||
@echo " GZIP_SUPPORT=[true|false] - Enable ZIP / GZ support (default=false)"
|
||||
@echo " JMA_SUPPORT=[true|false] - Enable JMA support (default=false)"
|
||||
@echo ""
|
||||
@echo "Example: $(MAKE) PLATFORM=x-gcc-lui GZIP_SUPPORT=true"
|
||||
@echo ""
|
||||
######################
|
||||
### bsnes makefile ###
|
||||
######################
|
||||
|
||||
ifeq ($(PLATFORM),)
|
||||
null_: help
|
||||
endif
|
||||
|
||||
##################################
|
||||
### platform-specific settings ###
|
||||
##################################
|
||||
|
||||
PREFIX = /usr/local
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-x86)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU `pkg-config --cflags gtk+-2.0`
|
||||
AS = yasm
|
||||
ASFLAGS = -f elf
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco.x86
|
||||
MIU = miu.gtk
|
||||
VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ)
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),x-gcc-x86-64)
|
||||
OS = unix
|
||||
CC = gcc
|
||||
CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_MIU `pkg-config --cflags gtk+-2.0`
|
||||
AS = yasm
|
||||
ASFLAGS = -f elf64
|
||||
LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao
|
||||
LIBCO = libco.x86-64
|
||||
MIU = miu.gtk
|
||||
VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ)
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-mingw-x86)
|
||||
OS = win
|
||||
CC = mingw32-gcc
|
||||
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN
|
||||
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
|
||||
LIBCO = libco.x86
|
||||
MIU = miu.win
|
||||
VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ)
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-visualc-x86)
|
||||
OS = win
|
||||
CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_MIU
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LIBCO = libco.x86
|
||||
MIU = miu.win
|
||||
VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ)
|
||||
endif
|
||||
|
||||
#####################################
|
||||
### compiler / assembler switches ###
|
||||
#####################################
|
||||
|
||||
ifeq ($(CC),gcc)
|
||||
OUT = -obsnes
|
||||
CPP = g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OUT = -obsnes
|
||||
CPP = mingw32-g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),cl)
|
||||
OUT = /Febsnes
|
||||
CPP = cl
|
||||
OBJ = obj
|
||||
CARGS = /c $< /Fo$@
|
||||
DEFINE = /D
|
||||
endif
|
||||
|
||||
ifeq ($(AS),nasm)
|
||||
ASARGS = $< -o $@
|
||||
endif
|
||||
|
||||
ifeq ($(AS),yasm)
|
||||
ASARGS = $< -o $@
|
||||
endif
|
||||
|
||||
###################
|
||||
### OS switches ###
|
||||
###################
|
||||
|
||||
ifeq ($(OS),unix)
|
||||
RM = rm -f
|
||||
endif
|
||||
|
||||
ifeq ($(OS),win)
|
||||
OUT := $(OUT).exe
|
||||
RM = del
|
||||
endif
|
||||
|
||||
####################################
|
||||
### main target and dependencies ###
|
||||
####################################
|
||||
|
||||
OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(MIU).$(OBJ) $(VAI) bstring.$(OBJ) \
|
||||
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) smemory.$(OBJ) \
|
||||
cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \
|
||||
bppu.$(OBJ) snes.$(OBJ) bsx.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) \
|
||||
sdd1.$(OBJ) cx4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) \
|
||||
obc1.$(OBJ) st010.$(OBJ)
|
||||
|
||||
ifeq ($(GZIP_SUPPORT),true)
|
||||
OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \
|
||||
gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \
|
||||
trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ)
|
||||
CFLAGS += $(DEFINE)GZIP_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(JMA_SUPPORT),true)
|
||||
OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \
|
||||
iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
|
||||
CFLAGS += $(DEFINE)JMA_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(OS),win)
|
||||
ifeq ($(CC),cl)
|
||||
OBJECTS += bsnes.res
|
||||
endif
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OBJECTS += bsnesrc.o
|
||||
endif
|
||||
endif
|
||||
|
||||
all: $(OBJECTS)
|
||||
$(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK)
|
||||
|
||||
######################
|
||||
### implicit rules ###
|
||||
######################
|
||||
|
||||
%.$(OBJ): $<
|
||||
$(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS))
|
||||
$(if $(filter %.s,$<),$(AS) $(ASFLAGS) $(ASARGS))
|
||||
$(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS))
|
||||
$(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS))
|
||||
|
||||
############
|
||||
### main ###
|
||||
############
|
||||
|
||||
main.$(OBJ): ui/main.cpp config/* \
|
||||
ui/* ui/vai/* \
|
||||
ui/miu/* ui/miu/loader/* ui/miu/settings/*
|
||||
|
||||
bsnes.res: ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc
|
||||
bsnesrc.o: ui/bsnes.rc ; windres -I data ui/bsnes.rc bsnesrc.o
|
||||
|
||||
##########
|
||||
### ui ###
|
||||
##########
|
||||
|
||||
video.direct3d.$(OBJ) : ui/vai/video/video.direct3d.cpp ui/vai/video/*
|
||||
video.directdraw.$(OBJ) : ui/vai/video/video.directdraw.cpp ui/vai/video/*
|
||||
video.gdi.$(OBJ) : ui/vai/video/video.gdi.cpp ui/vai/video/*
|
||||
video.gtk.$(OBJ) : ui/vai/video/video.gtk.cpp ui/vai/video/*
|
||||
video.xv.$(OBJ) : ui/vai/video/video.xv.cpp ui/vai/video/*
|
||||
audio.ao.$(OBJ) : ui/vai/audio/audio.ao.cpp ui/vai/audio/*
|
||||
audio.directsound.$(OBJ): ui/vai/audio/audio.directsound.cpp ui/vai/audio/*
|
||||
input.directinput.$(OBJ): ui/vai/input/input.directinput.cpp ui/vai/input/*
|
||||
input.x.$(OBJ) : ui/vai/input/input.x.cpp ui/vai/input/*
|
||||
|
||||
#############
|
||||
### libco ###
|
||||
#############
|
||||
|
||||
libco.x86.$(OBJ) : lib/libco/libco.x86.asm lib/libco/*
|
||||
libco.x86-64.$(OBJ): lib/libco/libco.x86-64.asm lib/libco/*
|
||||
libco.pcc.$(OBJ) : lib/libco/libco.ppc.s lib/libco/*
|
||||
libco.ppc64.$(OBJ) : lib/libco/libco.ppc64.s lib/libco/*
|
||||
|
||||
###########
|
||||
### miu ###
|
||||
###########
|
||||
|
||||
miu.gtk.$(OBJ): lib/miu.gtk/miu.gtk.cpp lib/miu.gtk/*
|
||||
miu.win.$(OBJ): lib/miu.win/miu.win.cpp lib/miu.win/*
|
||||
|
||||
#################
|
||||
### libraries ###
|
||||
#################
|
||||
|
||||
bstring.$(OBJ): lib/bstring.cpp lib/*
|
||||
|
||||
#################
|
||||
### utilities ###
|
||||
#################
|
||||
|
||||
reader.$(OBJ): reader/reader.cpp reader/*
|
||||
cart.$(OBJ) : cart/cart.cpp cart/*
|
||||
cheat.$(OBJ) : cheat/cheat.cpp cheat/*
|
||||
|
||||
##############
|
||||
### memory ###
|
||||
##############
|
||||
|
||||
memory.$(OBJ) : memory/memory.cpp memory/*
|
||||
bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/*
|
||||
smemory.$(OBJ): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/*
|
||||
|
||||
###########
|
||||
### cpu ###
|
||||
###########
|
||||
|
||||
cpu.$(OBJ) : cpu/cpu.cpp cpu/*
|
||||
scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/*
|
||||
|
||||
###########
|
||||
### smp ###
|
||||
###########
|
||||
|
||||
smp.$(OBJ) : smp/smp.cpp smp/*
|
||||
ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/*
|
||||
|
||||
###########
|
||||
### dsp ###
|
||||
###########
|
||||
|
||||
adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/*
|
||||
bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/*
|
||||
|
||||
###########
|
||||
### ppu ###
|
||||
###########
|
||||
|
||||
ppu.$(OBJ) : ppu/ppu.cpp ppu/*
|
||||
bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/*
|
||||
|
||||
############
|
||||
### snes ###
|
||||
############
|
||||
|
||||
snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/*
|
||||
|
||||
#####################
|
||||
### special chips ###
|
||||
#####################
|
||||
|
||||
bsx.$(OBJ) : chip/bsx/bsx.cpp chip/bsx/*
|
||||
superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/*
|
||||
srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/*
|
||||
sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||
cx4.$(OBJ) : chip/cx4/cx4.cpp chip/cx4/*
|
||||
dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||
dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||
dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||
dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||
obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/*
|
||||
st010.$(OBJ) : chip/st010/st010.cpp chip/st010/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
############
|
||||
|
||||
adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/*
|
||||
compress.$(OBJ): reader/zlib/compress.c reader/zlib/*
|
||||
crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/*
|
||||
deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/*
|
||||
gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/*
|
||||
inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/*
|
||||
inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/*
|
||||
inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/*
|
||||
ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/*
|
||||
trees.$(OBJ) : reader/zlib/trees.c reader/zlib/*
|
||||
unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/*
|
||||
zip.$(OBJ) : reader/zlib/zip.c reader/zlib/*
|
||||
zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/*
|
||||
|
||||
###########
|
||||
### jma ###
|
||||
###########
|
||||
|
||||
jma.$(OBJ) : reader/jma/jma.cpp reader/jma/*
|
||||
jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/*
|
||||
lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/*
|
||||
7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/*
|
||||
iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/*
|
||||
inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/*
|
||||
lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/*
|
||||
winout.$(OBJ) : reader/jma/winout.cpp reader/jma/*
|
||||
|
||||
####################
|
||||
### misc targets ###
|
||||
####################
|
||||
|
||||
install:
|
||||
install -m 775 bsnes $(PREFIX)/bin/bsnes
|
||||
install -m 775 data/bsnes.png $(PREFIX)/share/icons/bsnes.png
|
||||
|
||||
clean:
|
||||
-@$(RM) *.$(OBJ)
|
||||
-@$(RM) *.res
|
||||
-@$(RM) *.pgd
|
||||
-@$(RM) *.pgc
|
||||
-@$(RM) *.ilk
|
||||
-@$(RM) *.pdb
|
||||
-@$(RM) *.manifest
|
||||
|
||||
help:
|
||||
@echo "Usage: $(MAKE) PLATFORM=platform [options]"
|
||||
@echo ""
|
||||
@echo "Available platform targets:"
|
||||
@echo " x-gcc-x86 - Linux / BSD (x86) (requires yasm)"
|
||||
@echo " x-gcc-x86-64 - Linux / BSD (x86-64) (requires yasm)"
|
||||
@echo " win-mingw-x86 - Windows (x86) (requires nasm)"
|
||||
@echo " win-visualc-x86 - Windows (x86) (requires nasm)"
|
||||
@echo ""
|
||||
@echo "Available options:"
|
||||
@echo " GZIP_SUPPORT=[true|false] - Enable ZIP / GZ support (default=false)"
|
||||
@echo " JMA_SUPPORT=[true|false] - Enable JMA support (default=false)"
|
||||
@echo ""
|
||||
@echo "Example: $(MAKE) PLATFORM=x-gcc-lui GZIP_SUPPORT=true"
|
||||
@echo ""
|
||||
+54
-53
@@ -1,53 +1,54 @@
|
||||
#define BSNES_VERSION "0.026"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
#define CPUCORE sCPU
|
||||
#define SMPCORE sSMP
|
||||
#define DSPCORE bDSP
|
||||
#define PPUCORE bPPU
|
||||
|
||||
//#define FAVOR_ACCURACY
|
||||
#define FAVOR_SPEED
|
||||
|
||||
//game genie + pro action replay code support (~1-3% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
#if defined(PROCESSOR_X86)
|
||||
#define ARCH_LSB
|
||||
#include "lib/libco_x86.h"
|
||||
#elif defined(PROCESSOR_X86_64)
|
||||
#define ARCH_LSB
|
||||
#include "lib/libco_x86_64.h"
|
||||
#elif defined(PROCESSOR_G5)
|
||||
#define ARCH_MSB
|
||||
#else
|
||||
#error "unsupported processor"
|
||||
#endif
|
||||
|
||||
#include "lib/libbase.h"
|
||||
#include "lib/libfunction.h"
|
||||
#include "lib/libarray.h"
|
||||
#include "lib/libvector.h"
|
||||
#include "lib/libstring.h"
|
||||
#include "lib/libconfig.h"
|
||||
|
||||
//platform-specific global functions
|
||||
void alert(const char*, ...);
|
||||
void dprintf(const char*, ...);
|
||||
void dprintf(uint, const char*, ...);
|
||||
|
||||
namespace source {
|
||||
enum {
|
||||
none = 0,
|
||||
debug,
|
||||
cpu,
|
||||
ppu,
|
||||
smp,
|
||||
dsp,
|
||||
bus,
|
||||
};
|
||||
};
|
||||
|
||||
//various class interfaces
|
||||
#include "interface.h"
|
||||
#define BSNES_VERSION "0.027"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define BUSCORE sBus
|
||||
#define CPUCORE sCPU
|
||||
#define SMPCORE sSMP
|
||||
#define DSPCORE bDSP
|
||||
#define PPUCORE bPPU
|
||||
|
||||
//FAVOR_ACCURACY calculates RTO during frameskip, whereas FAVOR_SPEED does not
|
||||
//frameskip offers near-zero speedup if RTO is calculated
|
||||
//accuracy is not affected by this define when frameskipping is off
|
||||
|
||||
//#define FAVOR_ACCURACY
|
||||
#define FAVOR_SPEED
|
||||
|
||||
//game genie + pro action replay code support (~1-3% speed hit)
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
#if defined(PROCESSOR_X86) || defined(PROCESSOR_X86_64)
|
||||
#define ARCH_LSB
|
||||
#elif defined(PROCESSOR_PPC) || defined(PROCESSOR_PPC64)
|
||||
#define ARCH_MSB
|
||||
#else //guess
|
||||
#define ARCH_LSB
|
||||
#endif
|
||||
|
||||
#include "lib/libco.h"
|
||||
#include "lib/bbase.h"
|
||||
#include "lib/bfunction.h"
|
||||
#include "lib/barray.h"
|
||||
#include "lib/bvector.h"
|
||||
#include "lib/bkeymap.h"
|
||||
#include "lib/bstring.h"
|
||||
#include "lib/bconfig.h"
|
||||
|
||||
//platform-specific global functions
|
||||
void alert(const char*, ...);
|
||||
void dprintf(const char*, ...);
|
||||
void dprintf(uint, const char*, ...);
|
||||
|
||||
namespace source {
|
||||
enum {
|
||||
none = 0,
|
||||
debug,
|
||||
cpu,
|
||||
ppu,
|
||||
smp,
|
||||
dsp,
|
||||
bus,
|
||||
};
|
||||
};
|
||||
|
||||
#include "interface.h"
|
||||
@@ -82,6 +82,14 @@ void Cartridge::load_end() {
|
||||
memory::stBrom.write_protect(true);
|
||||
memory::stBram.write_protect(false);
|
||||
|
||||
char fn[PATH_MAX];
|
||||
strcpy(fn, cart.fn);
|
||||
modify_extension(fn, "cht");
|
||||
if(fexists(fn)) {
|
||||
cheat.clear();
|
||||
cheat.load(fn);
|
||||
}
|
||||
|
||||
cart.loaded = true;
|
||||
bus.load_cart();
|
||||
}
|
||||
@@ -106,6 +114,14 @@ bool Cartridge::unload() {
|
||||
safe_free(stB.rom);
|
||||
safe_free(stB.ram);
|
||||
|
||||
char fn[PATH_MAX];
|
||||
strcpy(fn, cart.fn);
|
||||
modify_extension(fn, "cht");
|
||||
if(cheat.count() > 0 || fexists(fn)) {
|
||||
cheat.save(fn);
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
cart.loaded = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
+41
-44
@@ -29,7 +29,7 @@ char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||
|
||||
//override path with user-specified folder, if one was defined
|
||||
if(config::path.save != "") {
|
||||
stringarray part;
|
||||
lstring part;
|
||||
split(part, "/", savefn);
|
||||
string fn = config::path.save();
|
||||
if(strend(fn, "/") == false) strcat(fn, "/");
|
||||
@@ -38,7 +38,7 @@ char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||
|
||||
//resolve relative path, if found
|
||||
if(strbegin(fn, "./") == true) {
|
||||
strltrim(fn, "./");
|
||||
ltrim(fn, "./");
|
||||
strcpy(savefn, config::path.base);
|
||||
strcat(savefn, fn);
|
||||
}
|
||||
@@ -50,53 +50,50 @@ char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||
dprintf("* Loading \"%s\"...", fn);
|
||||
|
||||
if(fexists(fn) == false) {
|
||||
return false;
|
||||
}
|
||||
if(fexists(fn) == false) return false;
|
||||
|
||||
switch(Reader::detect(fn)) {
|
||||
default:
|
||||
case Reader::RF_NORMAL: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = ff.size();
|
||||
data = ff.read();
|
||||
} break;
|
||||
|
||||
case Reader::RF_NORMAL: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = ff.size();
|
||||
data = ff.read();
|
||||
} break;
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = gf.size();
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = gf.size();
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
case Reader::RF_ZIP: {
|
||||
ZipReader zf(fn);
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
data = jf.read();
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
case Reader::RF_ZIP: {
|
||||
ZipReader zf(fn);
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
data = jf.read();
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
@make -r PLATFORM=win-mingw-lui
|
||||
::@make -r PLATFORM=win-mingw-lui GZIP_SUPPORT=true JMA_SUPPORT=true
|
||||
::@make -r PLATFORM=win-visualc-lui
|
||||
::@make -r PLATFORM=win-visualc-lui GZIP_SUPPORT=true JMA_SUPPORT=true
|
||||
@make -r PLATFORM=win-mingw-x86
|
||||
::@make -r PLATFORM=win-mingw-x86 GZIP_SUPPORT=true JMA_SUPPORT=true
|
||||
::@make -r PLATFORM=win-visualc-x86
|
||||
::@make -r PLATFORM=win-visualc-x86 GZIP_SUPPORT=true JMA_SUPPORT=true
|
||||
@move bsnes.exe ../bsnes.exe>nul
|
||||
@pause
|
||||
@@ -1,3 +1 @@
|
||||
#!/bin/sh
|
||||
make PLATFORM=x-gcc-lui
|
||||
#make PLATFORM=x-gcc-lui GZIP_SUPPORT=true JMA_SUPPORT=true
|
||||
make PLATFORM=x-gcc-x86
|
||||
+29
-40
@@ -10,17 +10,17 @@ Cheat cheat;
|
||||
*****/
|
||||
|
||||
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
||||
stringarray t, part;
|
||||
string t, part;
|
||||
strcpy(t, str);
|
||||
strlower(t);
|
||||
if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) {
|
||||
strlower(t());
|
||||
if(strlen(t) == 8 || (strlen(t) == 9 && t()[6] == ':')) {
|
||||
type = CT_PRO_ACTION_REPLAY;
|
||||
replace(t, ":", "");
|
||||
uint32 r = strhex(t);
|
||||
addr = r >> 8;
|
||||
data = r & 0xff;
|
||||
return true;
|
||||
} else if(strlen(t) == 9 && strptr(t)[4] == '-') {
|
||||
} else if(strlen(t) == 9 && t()[4] == '-') {
|
||||
type = CT_GAME_GENIE;
|
||||
replace(t, "-", "");
|
||||
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
||||
@@ -269,51 +269,40 @@ void Cheat::disable(uint32 n) {
|
||||
* cheat file manipulation routines
|
||||
*****/
|
||||
|
||||
/* file format: */
|
||||
/* nnnn-nnnn = status, "description" \r\n */
|
||||
/* ... */
|
||||
|
||||
bool Cheat::load(const char *fn) {
|
||||
FileReader rf(fn);
|
||||
if(!rf.ready())return false;
|
||||
|
||||
uint8 *raw_data = rf.read();
|
||||
stringarray data, line;
|
||||
raw_data[rf.size()] = 0;
|
||||
strcpy(data, (char*)raw_data);
|
||||
safe_free(raw_data);
|
||||
string data;
|
||||
if(!fread(data, fn)) return false;
|
||||
replace(data, "\r\n", "\n");
|
||||
qreplace(data, "=", ",");
|
||||
qreplace(data, " ", "");
|
||||
|
||||
lstring line;
|
||||
split(line, "\n", data);
|
||||
for(int i = 0; i < ::count(line); i++) {
|
||||
stringarray part;
|
||||
uint8 en = *(strptr(line[i]));
|
||||
if(en == '+') {
|
||||
strltrim(line[i], "+");
|
||||
} else if(en == '-') {
|
||||
strltrim(line[i], "-");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
qreplace(line[i], " ", "");
|
||||
qsplit(part, ",", line[i]);
|
||||
if(::count(part) != 2)continue;
|
||||
strunquote(part[1]);
|
||||
add(en == '+', strptr(part[0]), strptr(part[1]));
|
||||
lstring part;
|
||||
split(part, ",", line[i]);
|
||||
if(::count(part) != 3) continue;
|
||||
trim(part[2], "\"");
|
||||
add(part[1] == "enabled", part[0](), part[2]());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::save(const char *fn) {
|
||||
FileWriter wf(fn);
|
||||
if(!wf.ready())return false;
|
||||
|
||||
string data;
|
||||
char t[4096];
|
||||
strcpy(data, "");
|
||||
FILE *fp = fopen(fn, "wb");
|
||||
if(!fp) return false;
|
||||
for(int i = 0; i < cheat_count; i++) {
|
||||
sprintf(t, "%c%s, \"%s\"\r\n", index[i].enabled ? '+' : '-', index[i].code, index[i].desc);
|
||||
strcat(data, t);
|
||||
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
|
||||
index[i].code,
|
||||
index[i].enabled ? "enabled" : "disabled",
|
||||
index[i].desc);
|
||||
}
|
||||
|
||||
wf.write((uint8*)strptr(data), strlen(data));
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -323,12 +312,12 @@ char t[4096];
|
||||
|
||||
void Cheat::clear() {
|
||||
cheat_enabled = false;
|
||||
cheat_count = 0;
|
||||
cheat_count = 0;
|
||||
memset(mask, 0, 0x200000);
|
||||
for(int i = 0; i < CHEAT_LIMIT + 1; i++) {
|
||||
for(int i = 0; i <= CHEAT_LIMIT; i++) {
|
||||
index[i].enabled = false;
|
||||
index[i].addr = 0x000000;
|
||||
index[i].data = 0x00;
|
||||
index[i].addr = 0x000000;
|
||||
index[i].data = 0x00;
|
||||
strcpy(index[i].code, "");
|
||||
strcpy(index[i].desc, "");
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
@make PLATFORM=win-mingw-lui clean
|
||||
::@make PLATFORM=win-visualc-lui clean
|
||||
@make PLATFORM=win-mingw-x86 clean
|
||||
::@make PLATFORM=win-visualc-x86 clean
|
||||
+1
-2
@@ -1,2 +1 @@
|
||||
#!/bin/sh
|
||||
make PLATFORM=x-gcc-lui clean
|
||||
make PLATFORM=x-gcc-x86 clean
|
||||
@@ -15,14 +15,14 @@ string path(req_path);
|
||||
if(!strend(path, "/")) { strcat(path, "/"); }
|
||||
|
||||
if(strbegin(path, "./")) {
|
||||
strltrim(path, "./");
|
||||
ltrim(path(), "./");
|
||||
string temp;
|
||||
strcpy(temp, config::path.base);
|
||||
strcat(temp, path);
|
||||
strcpy(path, temp);
|
||||
}
|
||||
|
||||
stringarray part;
|
||||
lstring part;
|
||||
split(part, "/", file);
|
||||
strcat(path, part[count(part) - 1]);
|
||||
return path;
|
||||
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
echo "Warning: bsnes does not use a configure script"
|
||||
echo "To compile bsnes, use make ..."
|
||||
echo ""
|
||||
make #prints make usage instructions
|
||||
+37
-36
@@ -1,36 +1,37 @@
|
||||
#include "memory/memory.h"
|
||||
#include "memory/smemory/smemory.h"
|
||||
|
||||
#include "cpu/cpu.h"
|
||||
#include "cpu/scpu/scpu.h"
|
||||
|
||||
#include "smp/smp.h"
|
||||
#include "smp/ssmp/ssmp.h"
|
||||
|
||||
#include "dsp/dsp.h"
|
||||
//#include "dsp/adsp/adsp.h"
|
||||
#include "dsp/bdsp/bdsp.h"
|
||||
|
||||
#include "ppu/ppu.h"
|
||||
#include "ppu/bppu/bppu.h"
|
||||
|
||||
#include "snes/snes.h"
|
||||
#include "chip/chip.h"
|
||||
|
||||
#include "reader/reader.h"
|
||||
#include "cart/cart.h"
|
||||
#include "cheat/cheat.h"
|
||||
#include "config/config.h"
|
||||
|
||||
#ifdef INTERFACE_MAIN
|
||||
#include "config/config.cpp"
|
||||
#define extern
|
||||
#endif
|
||||
|
||||
extern BUSCORE bus;
|
||||
extern CPUCORE cpu;
|
||||
extern SMPCORE smp;
|
||||
extern DSPCORE dsp;
|
||||
extern PPUCORE ppu;
|
||||
|
||||
#undef extern
|
||||
#include "reader/reader.h"
|
||||
#include "cheat/cheat.h"
|
||||
#include "config/config.h"
|
||||
|
||||
#include "memory/memory.h"
|
||||
#include "memory/smemory/smemory.h"
|
||||
|
||||
#include "cart/cart.h"
|
||||
|
||||
#include "cpu/cpu.h"
|
||||
#include "cpu/scpu/scpu.h"
|
||||
|
||||
#include "smp/smp.h"
|
||||
#include "smp/ssmp/ssmp.h"
|
||||
|
||||
#include "dsp/dsp.h"
|
||||
//#include "dsp/adsp/adsp.h"
|
||||
#include "dsp/bdsp/bdsp.h"
|
||||
|
||||
#include "ppu/ppu.h"
|
||||
#include "ppu/bppu/bppu.h"
|
||||
|
||||
#include "snes/snes.h"
|
||||
#include "chip/chip.h"
|
||||
|
||||
#ifdef INTERFACE_MAIN
|
||||
#include "config/config.cpp"
|
||||
#define extern
|
||||
#endif
|
||||
|
||||
extern BUSCORE bus;
|
||||
extern CPUCORE cpu;
|
||||
extern SMPCORE smp;
|
||||
extern DSPCORE dsp;
|
||||
extern PPUCORE ppu;
|
||||
|
||||
#undef extern
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
barray : version 0.10 ~byuu (2007-11-29)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef BARRAY_H
|
||||
#define BARRAY_H
|
||||
|
||||
template<typename T> class array {
|
||||
protected:
|
||||
T *pool;
|
||||
uint poolsize, buffersize;
|
||||
|
||||
uint findsize(uint size) {
|
||||
if(size <= 0x100) return 0x100;
|
||||
if(size <= 0x400) return 0x400;
|
||||
if(size <= 0x1000) return 0x1000;
|
||||
if(size <= 0x4000) return 0x4000;
|
||||
if(size <= 0x10000) return 0x10000;
|
||||
if(size <= 0x40000) return 0x40000;
|
||||
if(size <= 0x100000) return 0x100000;
|
||||
|
||||
return (size + 0x100000) & ~0xfffff;
|
||||
}
|
||||
|
||||
public:
|
||||
uint size() { return buffersize; }
|
||||
uint capacity() { return poolsize; }
|
||||
|
||||
void reset() {
|
||||
safe_free(pool);
|
||||
poolsize = 0;
|
||||
buffersize = 0;
|
||||
}
|
||||
|
||||
void reserve(uint size) {
|
||||
if(size == poolsize) return;
|
||||
if(size < poolsize) buffersize = size;
|
||||
|
||||
pool = (T*)realloc(pool, sizeof(T) * size);
|
||||
poolsize = size;
|
||||
}
|
||||
|
||||
T* get(uint size = 0) {
|
||||
if(size > buffersize) resize(size);
|
||||
if(size > buffersize) throw "array[] out of bounds";
|
||||
return pool;
|
||||
}
|
||||
|
||||
void add(T data) {
|
||||
operator[](buffersize) = data;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
memset(pool, 0, sizeof(T) * buffersize);
|
||||
}
|
||||
|
||||
void resize(uint size) {
|
||||
reserve(findsize(size));
|
||||
buffersize = size;
|
||||
}
|
||||
|
||||
array() {
|
||||
pool = 0;
|
||||
poolsize = 0;
|
||||
buffersize = 0;
|
||||
}
|
||||
|
||||
~array() { reset(); }
|
||||
|
||||
array& operator=(array &source) {
|
||||
safe_free(pool);
|
||||
buffersize = source.buffersize;
|
||||
poolsize = source.poolsize;
|
||||
pool = (T*)realloc(pool, sizeof(T) * poolsize); //allocate entire pool size ...
|
||||
memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline T& operator[](int index) {
|
||||
if(index >= buffersize) resize(index + 1);
|
||||
if(index >= buffersize) throw "array[] out of bounds";
|
||||
return pool[index];
|
||||
}
|
||||
};
|
||||
|
||||
#endif //ifndef BARRAY_H
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
libbase : version 0.11a ~byuu (2007-10-14)
|
||||
bbase : version 0.12 ~byuu (2007-12-12)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBBASE_H
|
||||
#define LIBBASE_H
|
||||
#ifndef BBASE_H
|
||||
#define BBASE_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
@@ -109,7 +109,27 @@ struct passwd *userinfo = getpwuid(getuid());
|
||||
#endif
|
||||
|
||||
/*****
|
||||
* templates
|
||||
* template classes
|
||||
*****/
|
||||
|
||||
class noncopyable {
|
||||
protected:
|
||||
noncopyable() {}
|
||||
~noncopyable() {}
|
||||
|
||||
private:
|
||||
noncopyable(const noncopyable&);
|
||||
const noncopyable& operator=(const noncopyable&);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct base_from_member {
|
||||
T value;
|
||||
base_from_member(T value_) : value(value_) {}
|
||||
};
|
||||
|
||||
/*****
|
||||
* template functions
|
||||
*****/
|
||||
|
||||
template<typename T> inline void safe_free(T &handle) {
|
||||
@@ -324,4 +344,4 @@ uint32 crc32 = ~0;
|
||||
return ~crc32;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif //ifndef BBASE_H
|
||||
@@ -1,54 +1,52 @@
|
||||
/*
|
||||
libconfig : version 0.15 ~byuu (2007-11-01)
|
||||
bconfig : version 0.16 ~byuu (2007-11-28)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCONFIG_H
|
||||
#define LIBCONFIG_H
|
||||
#ifndef BCONFIG_H
|
||||
#define BCONFIG_H
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libarray.h"
|
||||
#include "libstring.h"
|
||||
#include "bbase.h"
|
||||
#include "barray.h"
|
||||
#include "bstring.h"
|
||||
|
||||
class Setting;
|
||||
|
||||
class Config { public:
|
||||
array<Setting*> list;
|
||||
uint list_count;
|
||||
class Config {
|
||||
public:
|
||||
array<Setting*> list;
|
||||
uint list_count;
|
||||
|
||||
string data;
|
||||
stringarray line, part, subpart;
|
||||
string data;
|
||||
lstring line, part, subpart;
|
||||
|
||||
bool load(const char *fn);
|
||||
bool save(const char *fn);
|
||||
bool load(const string &fn) { return load(strptr(fn)); }
|
||||
bool save(const string &fn) { return save(strptr(fn)); }
|
||||
void add(Setting *setting) { list[list_count++] = setting; }
|
||||
|
||||
Config() : list_count(0) {}
|
||||
};
|
||||
|
||||
class Setting { public:
|
||||
uint type;
|
||||
char *name, *desc, *def;
|
||||
|
||||
enum Type {
|
||||
Integer,
|
||||
String,
|
||||
};
|
||||
class Setting {
|
||||
public:
|
||||
enum Type {
|
||||
Integer,
|
||||
String,
|
||||
} type;
|
||||
char *name, *desc, *def;
|
||||
|
||||
virtual void set(const char *input) = 0;
|
||||
virtual void get(string &output) = 0;
|
||||
};
|
||||
|
||||
class IntegerSetting : public Setting { public:
|
||||
uint ifmt, data, idef;
|
||||
|
||||
enum Format {
|
||||
Boolean,
|
||||
Decimal,
|
||||
Hex,
|
||||
};
|
||||
class IntegerSetting : public Setting {
|
||||
public:
|
||||
enum Format {
|
||||
Boolean,
|
||||
Decimal,
|
||||
Hex,
|
||||
} ifmt;
|
||||
uint data, idef;
|
||||
|
||||
void set(const char *input) {
|
||||
if(ifmt == Boolean) { data = !strcmp(input, "true"); }
|
||||
@@ -57,9 +55,10 @@ enum Format {
|
||||
}
|
||||
|
||||
void get(string &output) {
|
||||
if(ifmt == Boolean) { sprintf(output, "%s", data ? "true" : "false"); }
|
||||
if(ifmt == Decimal) { sprintf(output, "%d", data); }
|
||||
if(ifmt == Hex) { sprintf(output, "0x%x", data); }
|
||||
output.reserve(64);
|
||||
if(ifmt == Boolean) { sprintf(output(), "%s", data ? "true" : "false"); }
|
||||
if(ifmt == Decimal) { sprintf(output(), "%d", data); }
|
||||
if(ifmt == Hex) { sprintf(output(), "0x%x", data); }
|
||||
}
|
||||
|
||||
uint operator()() { return data; }
|
||||
@@ -72,7 +71,7 @@ enum Format {
|
||||
template<typename T> bool operator<=(T x) { return (T(data) <= x); }
|
||||
template<typename T> bool operator< (T x) { return (T(data) < x); }
|
||||
|
||||
IntegerSetting(Config *parent, const char *r_name, const char *r_desc, uint r_format, uint r_data) {
|
||||
IntegerSetting(Config *parent, const char *r_name, const char *r_desc, Format r_format, uint r_data) {
|
||||
type = Setting::Integer;
|
||||
name = strdup(r_name);
|
||||
desc = strdup(r_desc);
|
||||
@@ -80,25 +79,26 @@ enum Format {
|
||||
data = idef = r_data;
|
||||
string t;
|
||||
get(t);
|
||||
def = strdup(strptr(t));
|
||||
def = strdup(t);
|
||||
|
||||
if(parent) { parent->add(this); }
|
||||
}
|
||||
|
||||
~IntegerSetting() {
|
||||
free(name);
|
||||
free(desc);
|
||||
free(def);
|
||||
safe_free(name);
|
||||
safe_free(desc);
|
||||
safe_free(def);
|
||||
}
|
||||
};
|
||||
|
||||
class StringSetting : public Setting { public:
|
||||
string data;
|
||||
void set(const char *input) { data = input; strunquote(data); }
|
||||
void get(string &output) { output = data; strquote(output); }
|
||||
class StringSetting : public Setting {
|
||||
public:
|
||||
string data;
|
||||
void set(const char *input) { data = input; trim(data(), "\""); }
|
||||
void get(string &output) { output = string() << "\"" << data << "\""; }
|
||||
|
||||
const char* operator()() { return strptr(data); }
|
||||
operator const char*() { return strptr(data); }
|
||||
char* operator()() { return data(); }
|
||||
operator const char*() { return data; }
|
||||
StringSetting &operator=(const char *x) { data = x; return *this; }
|
||||
bool operator==(const char *x) { return !strcmp(data, x); }
|
||||
bool operator!=(const char *x) { return strcmp(data, x); }
|
||||
@@ -110,15 +110,15 @@ string data;
|
||||
data = r_data;
|
||||
string t;
|
||||
get(t);
|
||||
def = strdup(strptr(t));
|
||||
def = strdup(t);
|
||||
|
||||
if(parent) { parent->add(this); }
|
||||
}
|
||||
|
||||
~StringSetting() {
|
||||
free(name);
|
||||
free(desc);
|
||||
free(def);
|
||||
safe_free(name);
|
||||
safe_free(desc);
|
||||
safe_free(def);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -145,12 +145,12 @@ char *buffer = (char*)malloc(fsize + 1);
|
||||
|
||||
for(int i = 0; i < count(line); i++) {
|
||||
if(strlen(line[i]) == 0)continue;
|
||||
if(*strptr(line[i]) == '#')continue;
|
||||
if(*line[i] == '#')continue;
|
||||
|
||||
qsplit(part, "=", line[i]);
|
||||
for(int l = 0; l < list_count; l++) {
|
||||
if(!strcmp(list[l]->name, part[0])) {
|
||||
list[l]->set(strptr(part[1]));
|
||||
list[l]->set(part[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -170,16 +170,16 @@ string t;
|
||||
replace(data, "\r\n", "\n");
|
||||
split(line, "\n", data);
|
||||
for(int l = 0; l < count(line); l++) {
|
||||
if(line[l] != "") { fprintf(fp, "# %s\r\n", strptr(line[l])); }
|
||||
if(line[l] != "") { fprintf(fp, "# %s\r\n", line[l]()); }
|
||||
}
|
||||
|
||||
fprintf(fp, "# (default = %s)\r\n", list[i]->def);
|
||||
list[i]->get(t);
|
||||
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, strptr(t));
|
||||
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, t());
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif //ifndef BCONFIG_H
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
libfunction : version 0.06 ~byuu (2007-10-14)
|
||||
bfunction : version 0.06 ~byuu (2007-10-14)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBFUNCTION_H
|
||||
#define LIBFUNCTION_H
|
||||
#ifndef BFUNCTION_H
|
||||
#define BFUNCTION_H
|
||||
|
||||
//prologue
|
||||
|
||||
@@ -19,7 +19,7 @@ template<typename T> class function;
|
||||
#define PL
|
||||
#define CL
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 1
|
||||
|
||||
@@ -28,7 +28,7 @@ template<typename T> class function;
|
||||
#define PL P1 p1
|
||||
#define CL p1
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 2
|
||||
|
||||
@@ -37,7 +37,7 @@ template<typename T> class function;
|
||||
#define PL P1 p1, P2 p2
|
||||
#define CL p1, p2
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 3
|
||||
|
||||
@@ -46,7 +46,7 @@ template<typename T> class function;
|
||||
#define PL P1 p1, P2 p2, P3 p3
|
||||
#define CL p1, p2, p3
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 4
|
||||
|
||||
@@ -55,7 +55,7 @@ template<typename T> class function;
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4
|
||||
#define CL p1, p2, p3, p4
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 5
|
||||
|
||||
@@ -64,7 +64,7 @@ template<typename T> class function;
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
|
||||
#define CL p1, p2, p3, p4, p5
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 6
|
||||
|
||||
@@ -73,7 +73,7 @@ template<typename T> class function;
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
|
||||
#define CL p1, p2, p3, p4, p5, p6
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 7
|
||||
|
||||
@@ -82,7 +82,7 @@ template<typename T> class function;
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//parameters = 8
|
||||
|
||||
@@ -91,13 +91,14 @@ template<typename T> class function;
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7, p8
|
||||
|
||||
#include "libfunction.h"
|
||||
#include "bfunction.h"
|
||||
|
||||
//epilogue
|
||||
|
||||
#undef TN
|
||||
#define BFUNCTION_TH
|
||||
|
||||
#else //defined(LIBFUNCTION_H)
|
||||
#elif !defined(BFUNCTION_TH)
|
||||
|
||||
//function implementation template class
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
libkeymap : version 0.02 ~byuu (2007-05-28)
|
||||
bkeymap : version 0.02 ~byuu (2007-05-28)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBKEYMAP_H
|
||||
#define LIBKEYMAP_H
|
||||
#ifndef BKEYMAP_H
|
||||
#define BKEYMAP_H
|
||||
|
||||
namespace keymap {
|
||||
|
||||
@@ -306,4 +307,4 @@ static const char *find(uint16 key) {
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif //ifndef BKEYMAP_H
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "bstring.h"
|
||||
|
||||
#include "bstring/bstring.list.cpp"
|
||||
#include "bstring/bstring.strl.cpp"
|
||||
#include "bstring/bstring.math.cpp"
|
||||
#include "bstring/bstring.misc.cpp"
|
||||
#include "bstring/bstring.replace.cpp"
|
||||
#include "bstring/bstring.split.cpp"
|
||||
#include "bstring/bstring.trim.cpp"
|
||||
|
||||
void string::reserve(uint size_) {
|
||||
if(size_ > size) {
|
||||
size = size_;
|
||||
data = (char*)realloc(data, size + 1);
|
||||
data[size] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//implicit-conversion, read-only
|
||||
string::operator const char*() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
//explicit-coversion, read-write
|
||||
char* string::operator()() {
|
||||
return data;
|
||||
}
|
||||
|
||||
//index, read-write
|
||||
char& string::operator[](const uint index) {
|
||||
reserve(index);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
string& string::operator=(const int num) {
|
||||
itoa(*this, num);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator=(const char *str) {
|
||||
strcpy(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator=(const string &str) {
|
||||
strcpy(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator<<(const int num) {
|
||||
string temp(num);
|
||||
strcat(*this, temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator<<(const char *str) {
|
||||
strcat(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool string::operator==(const char *str) { return strcmp(data, str) == 0; }
|
||||
bool string::operator!=(const char *str) { return strcmp(data, str) != 0; }
|
||||
bool string::operator< (const char *str) { return strcmp(data, str) < 0; }
|
||||
bool string::operator<=(const char *str) { return strcmp(data, str) <= 0; }
|
||||
bool string::operator> (const char *str) { return strcmp(data, str) > 0; }
|
||||
bool string::operator>=(const char *str) { return strcmp(data, str) >= 0; }
|
||||
|
||||
string::string() {
|
||||
size = 64;
|
||||
data = (char*)malloc(size + 1);
|
||||
*data = 0;
|
||||
}
|
||||
|
||||
string::string(const int source) {
|
||||
size = 64;
|
||||
data = (char*)malloc(size + 1);
|
||||
*data = 0;
|
||||
itoa(*this, source);
|
||||
}
|
||||
|
||||
string::string(const char *source) {
|
||||
size = strlen(source);
|
||||
data = (char*)malloc(size + 1);
|
||||
strcpy(data, source);
|
||||
}
|
||||
|
||||
string::string(const string &source) {
|
||||
size = strlen(source);
|
||||
data = (char*)malloc(size + 1);
|
||||
strcpy(data, source);
|
||||
}
|
||||
|
||||
string::~string() {
|
||||
safe_free(data);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
bstring : version 0.01a ~byuu (2007-12-12)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef BSTRING_H
|
||||
#define BSTRING_H
|
||||
|
||||
#include "bbase.h"
|
||||
#include "bvector.h"
|
||||
|
||||
class string;
|
||||
typedef linear_vector<string> lstring;
|
||||
|
||||
uint count(lstring&);
|
||||
int find(lstring &str, const char *key);
|
||||
|
||||
uint strlcpy(char *dest, const char *src, uint length);
|
||||
uint strlcat(char *dest, const char *src, uint length);
|
||||
uint strlcpy(string &dest, const char *src, uint length);
|
||||
uint strlcat(string &dest, const char *src, uint length);
|
||||
|
||||
int strmath(const char *str);
|
||||
|
||||
char chrlower(char c);
|
||||
char chrupper(char c);
|
||||
int stricmp(const char *dest, const char *src);
|
||||
void strcpy(string &dest, const char *src);
|
||||
void strcat(string &dest, const char *src);
|
||||
string substr(string &dest, const char *src, uint start = 0, uint length = 0);
|
||||
char* strlower(char *str);
|
||||
char* strupper(char *str);
|
||||
string& strlower(string &str);
|
||||
string& strupper(string &str);
|
||||
int strpos(const char *str, const char *key);
|
||||
int qstrpos(const char *str, const char *key);
|
||||
char* strtr(char *dest, const char *before, const char *after);
|
||||
string& strtr(string &dest, const char *before, const char *after);
|
||||
bool strbegin(const char *str, const char *key);
|
||||
bool stribegin(const char *str, const char *key);
|
||||
bool strend(const char *str, const char *key);
|
||||
bool striend(const char *str, const char *key);
|
||||
|
||||
uint strhex(const char *str);
|
||||
uint strdec(const char *str);
|
||||
uint strbin(const char *str);
|
||||
|
||||
string& utoa(string &str, uint num);
|
||||
string& itoa(string &str, uint num);
|
||||
string& htoa(string &str, uint num);
|
||||
string& btoa(string &str, uint num);
|
||||
|
||||
bool fread(string &str, const char *filename);
|
||||
|
||||
string& replace(string &str, const char *key, const char *token);
|
||||
string& qreplace(string &str, const char *key, const char *token);
|
||||
|
||||
void split(lstring &dest, const char *key, const char *src);
|
||||
void qsplit(lstring &dest, const char *key, const char *src);
|
||||
|
||||
char* ltrim(char *str, const char *key = " ");
|
||||
char* rtrim(char *str, const char *key = " ");
|
||||
char* trim(char *str, const char *key = " ");
|
||||
string& ltrim(string &str, const char *key = " ");
|
||||
string& rtrim(string &str, const char *key = " ");
|
||||
string& trim(string &str, const char *key = " ");
|
||||
|
||||
class string {
|
||||
public:
|
||||
char *data;
|
||||
uint size;
|
||||
|
||||
void reserve(uint size_);
|
||||
|
||||
operator const char*() const;
|
||||
char* operator()();
|
||||
char& operator[](const uint);
|
||||
|
||||
string& operator=(const int num);
|
||||
string& operator=(const char *str);
|
||||
string& operator=(const string &str);
|
||||
string& operator<<(const int num);
|
||||
string& operator<<(const char *str);
|
||||
|
||||
bool operator==(const char *str);
|
||||
bool operator!=(const char *str);
|
||||
bool operator< (const char *str);
|
||||
bool operator<=(const char *str);
|
||||
bool operator> (const char *str);
|
||||
bool operator>=(const char *str);
|
||||
|
||||
string();
|
||||
string(const int num);
|
||||
string(const char *source);
|
||||
string(const string &source);
|
||||
~string();
|
||||
};
|
||||
|
||||
#endif //ifndef BSTRING_H
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifdef BSTRING_H
|
||||
|
||||
uint count(lstring &str) {
|
||||
return str.size();
|
||||
}
|
||||
|
||||
int find(lstring &str, const char *key) {
|
||||
for(uint i = 0; i < count(str); i++) {
|
||||
if(str[i] == key) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif //ifdef BSTRING_H
|
||||
@@ -1,121 +1,194 @@
|
||||
/*
|
||||
c-style Math Evaluator v1.0 (07/03/2006)
|
||||
Algorithm: Recursive Descent Processor
|
||||
Written by: gladius
|
||||
Optimized by: gladius and byuu
|
||||
Public Domain
|
||||
*/
|
||||
|
||||
#define maxlevel 12
|
||||
int strmath_rdp(const char *&s, int level = 0) {
|
||||
if(level == maxlevel) {
|
||||
if(*s == '(') {
|
||||
int result = strmath_rdp(++s, 0);
|
||||
s++;
|
||||
return result;
|
||||
} else if(*s == '+') {
|
||||
return +strmath_rdp(++s, maxlevel);
|
||||
} else if(*s == '-') {
|
||||
return -strmath_rdp(++s, maxlevel);
|
||||
} else if(*s == '!') {
|
||||
return !strmath_rdp(++s, maxlevel);
|
||||
} else if(*s == '~') {
|
||||
return ~strmath_rdp(++s, maxlevel);
|
||||
} else if(*s >= '0' && *s <= '9') {
|
||||
int num, len;
|
||||
sscanf(s, "%d%n", &num, &len);
|
||||
s += len;
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
int lhs = strmath_rdp(s, level + 1);
|
||||
while(*s) {
|
||||
int a = *s;
|
||||
int b = *s ? *(s + 1) : 0;
|
||||
switch(level) {
|
||||
case 0:
|
||||
if(a == '?')break;
|
||||
return lhs;
|
||||
case 1:
|
||||
if(a == '|' && b == '|') { s++; break; }
|
||||
return lhs;
|
||||
case 2:
|
||||
if(a == '^' && b == '^') { s++; break; }
|
||||
return lhs;
|
||||
case 3:
|
||||
if(a == '&' && b == '&') { s++; break; }
|
||||
return lhs;
|
||||
case 4:
|
||||
if(a == '|' && b != '|')break;
|
||||
return lhs;
|
||||
case 5:
|
||||
if(a == '^' && b != '^')break;
|
||||
return lhs;
|
||||
case 6:
|
||||
if(a == '&' && b != '&')break;
|
||||
return lhs;
|
||||
case 7:
|
||||
if(a == '=' && b == '=') { s++; break; }
|
||||
if(a == '!' && b == '=') { s++; break; }
|
||||
return lhs;
|
||||
case 8:
|
||||
if(a == '<' && b == '=') { s++; break; }
|
||||
if(a == '>' && b == '=') { s++; break; }
|
||||
if(a == '<')break;
|
||||
if(a == '>')break;
|
||||
return lhs;
|
||||
case 9:
|
||||
if(a == '<' && b == '<') { s++; break; }
|
||||
if(a == '>' && b == '>') { s++; break; }
|
||||
return lhs;
|
||||
case 10:
|
||||
if(a == '+')break;
|
||||
if(a == '-')break;
|
||||
return lhs;
|
||||
case 11:
|
||||
if(a == '*')break;
|
||||
if(a == '/')break;
|
||||
if(a == '%')break;
|
||||
return lhs;
|
||||
}
|
||||
if(a == '?') {
|
||||
int tr = strmath_rdp(++s, level);
|
||||
int fr = strmath_rdp(++s, level);
|
||||
lhs = (lhs) ? tr : fr;
|
||||
} else {
|
||||
int rhs = strmath_rdp(++s, level + 1);
|
||||
if (a == '|' && b == '|') lhs = (lhs || rhs);
|
||||
else if(a == '^' && b == '^') lhs = (!lhs != !rhs);
|
||||
else if(a == '&' && b == '&') lhs = (lhs && rhs);
|
||||
else if(a == '|' && b != '|') lhs |= rhs;
|
||||
else if(a == '^' && b != '^') lhs ^= rhs;
|
||||
else if(a == '&' && b != '&') lhs &= rhs;
|
||||
else if(a == '=' && b == '=') lhs = (lhs == rhs);
|
||||
else if(a == '!' && b == '=') lhs = (lhs != rhs);
|
||||
else if(a == '<' && b == '=') lhs = (lhs <= rhs);
|
||||
else if(a == '>' && b == '=') lhs = (lhs >= rhs);
|
||||
else if(a == '<' && b != '<') lhs = (lhs < rhs);
|
||||
else if(a == '>' && b != '>') lhs = (lhs > rhs);
|
||||
else if(a == '<' && b == '<') lhs <<= rhs;
|
||||
else if(a == '>' && b == '>') lhs >>= rhs;
|
||||
else if(a == '+') lhs += rhs;
|
||||
else if(a == '-') lhs -= rhs;
|
||||
else if(a == '*') lhs *= rhs;
|
||||
else if(a == '/') lhs /= rhs;
|
||||
else if(a == '%') lhs %= rhs;
|
||||
}
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
#undef maxlevel
|
||||
|
||||
int strmath(const char *str) {
|
||||
return strmath_rdp(str);
|
||||
}
|
||||
|
||||
#ifdef __LIBSTRING
|
||||
int strmath(const string &str) {
|
||||
return strmath(strptr(str));
|
||||
}
|
||||
#endif
|
||||
#ifdef BSTRING_H
|
||||
|
||||
/*
|
||||
recursive descent math processor v0.02 (2007-11-28)
|
||||
authors: gladius, byuu
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
void strmath_space(const char *&s) {
|
||||
while(*s == ' ' || *s == '\t')s++;
|
||||
}
|
||||
|
||||
int strmath_number(const char *&s) {
|
||||
int result = 0;
|
||||
enum type { dec, hex, bin, oct };
|
||||
type t = dec;
|
||||
if(*s == '0') {
|
||||
s++;
|
||||
if(*s == 'x' || *s == 'X') { s++; t = hex; }
|
||||
else if(*s == 'b' || *s == 'B') { s++; t = bin; }
|
||||
else { t = oct; }
|
||||
} else if(*s == '$') {
|
||||
s++;
|
||||
t = hex;
|
||||
} else if(*s == '%') {
|
||||
s++;
|
||||
t = bin;
|
||||
}
|
||||
|
||||
switch(t) {
|
||||
|
||||
case dec: {
|
||||
while(true) {
|
||||
char x = *s;
|
||||
if(x >= '0' && x <= '9')x = x - '0';
|
||||
else break;
|
||||
result = result * 10 + x;
|
||||
s++;
|
||||
}
|
||||
} break;
|
||||
|
||||
case hex: {
|
||||
while(true) {
|
||||
char x = *s;
|
||||
if(x >= '0' && x <= '9')x = x - '0';
|
||||
else if(x >= 'a' && x <= 'f')x = x - 'a' + 0x0a;
|
||||
else if(x >= 'A' && x <= 'F')x = x - 'A' + 0x0a;
|
||||
else break;
|
||||
result = result * 16 + x;
|
||||
s++;
|
||||
}
|
||||
} break;
|
||||
|
||||
case bin: {
|
||||
while(true) {
|
||||
char x = *s;
|
||||
if(x >= '0' && x <= '1')x = x - '0';
|
||||
else break;
|
||||
result = result * 2 + x;
|
||||
s++;
|
||||
}
|
||||
} break;
|
||||
|
||||
case oct: {
|
||||
while(true) {
|
||||
char x = *s;
|
||||
if(x >= '0' && x <= '7')x = x - '0';
|
||||
else break;
|
||||
result = result * 8 + x;
|
||||
s++;
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
int num, len;
|
||||
sscanf(s, "%d%n", &num, &len);
|
||||
s += len;
|
||||
return num;
|
||||
}
|
||||
|
||||
#define maxlevel 12
|
||||
int strmath_rdp(const char *&s, int level = 0) {
|
||||
strmath_space(s);
|
||||
|
||||
if(level == maxlevel) {
|
||||
if(*s == '(') {
|
||||
int result = strmath_rdp(++s, 0);
|
||||
s++;
|
||||
return result;
|
||||
} else if(*s == '+') {
|
||||
return +strmath_rdp(++s, maxlevel);
|
||||
} else if(*s == '-') {
|
||||
return -strmath_rdp(++s, maxlevel);
|
||||
} else if(*s == '!') {
|
||||
return !strmath_rdp(++s, maxlevel);
|
||||
} else if(*s == '~') {
|
||||
return ~strmath_rdp(++s, maxlevel);
|
||||
} else if((*s >= '0' && *s <= '9') || *s == '$' || *s == '%') {
|
||||
return strmath_number(s);
|
||||
} else {
|
||||
return 0; //error
|
||||
}
|
||||
}
|
||||
|
||||
int lhs = strmath_rdp(s, level + 1);
|
||||
strmath_space(s);
|
||||
while(*s) {
|
||||
int a = *s;
|
||||
int b = *s ? *(s + 1) : 0;
|
||||
switch(level) {
|
||||
case 0:
|
||||
if(a == '?')break;
|
||||
return lhs;
|
||||
case 1:
|
||||
if(a == '|' && b == '|') { s++; break; }
|
||||
return lhs;
|
||||
case 2:
|
||||
if(a == '^' && b == '^') { s++; break; }
|
||||
return lhs;
|
||||
case 3:
|
||||
if(a == '&' && b == '&') { s++; break; }
|
||||
return lhs;
|
||||
case 4:
|
||||
if(a == '|' && b != '|')break;
|
||||
return lhs;
|
||||
case 5:
|
||||
if(a == '^' && b != '^')break;
|
||||
return lhs;
|
||||
case 6:
|
||||
if(a == '&' && b != '&')break;
|
||||
return lhs;
|
||||
case 7:
|
||||
if(a == '=' && b == '=') { s++; break; }
|
||||
if(a == '!' && b == '=') { s++; break; }
|
||||
return lhs;
|
||||
case 8:
|
||||
if(a == '<' && b == '=') { s++; break; }
|
||||
if(a == '>' && b == '=') { s++; break; }
|
||||
if(a == '<')break;
|
||||
if(a == '>')break;
|
||||
return lhs;
|
||||
case 9:
|
||||
if(a == '<' && b == '<') { s++; break; }
|
||||
if(a == '>' && b == '>') { s++; break; }
|
||||
return lhs;
|
||||
case 10:
|
||||
if(a == '+')break;
|
||||
if(a == '-')break;
|
||||
return lhs;
|
||||
case 11:
|
||||
if(a == '*')break;
|
||||
if(a == '/')break;
|
||||
if(a == '%')break;
|
||||
return lhs;
|
||||
}
|
||||
if(a == '?') {
|
||||
int tr = strmath_rdp(++s, level);
|
||||
int fr = strmath_rdp(++s, level);
|
||||
lhs = (lhs) ? tr : fr;
|
||||
} else {
|
||||
int rhs = strmath_rdp(++s, level + 1);
|
||||
if (a == '|' && b == '|') lhs = (lhs || rhs);
|
||||
else if(a == '^' && b == '^') lhs = (!lhs != !rhs);
|
||||
else if(a == '&' && b == '&') lhs = (lhs && rhs);
|
||||
else if(a == '|' && b != '|') lhs |= rhs;
|
||||
else if(a == '^' && b != '^') lhs ^= rhs;
|
||||
else if(a == '&' && b != '&') lhs &= rhs;
|
||||
else if(a == '=' && b == '=') lhs = (lhs == rhs);
|
||||
else if(a == '!' && b == '=') lhs = (lhs != rhs);
|
||||
else if(a == '<' && b == '=') lhs = (lhs <= rhs);
|
||||
else if(a == '>' && b == '=') lhs = (lhs >= rhs);
|
||||
else if(a == '<' && b != '<') lhs = (lhs < rhs);
|
||||
else if(a == '>' && b != '>') lhs = (lhs > rhs);
|
||||
else if(a == '<' && b == '<') lhs <<= rhs;
|
||||
else if(a == '>' && b == '>') lhs >>= rhs;
|
||||
else if(a == '+') lhs += rhs;
|
||||
else if(a == '-') lhs -= rhs;
|
||||
else if(a == '*') lhs *= rhs;
|
||||
else if(a == '/') lhs /= rhs;
|
||||
else if(a == '%') lhs %= rhs;
|
||||
}
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
#undef maxlevel
|
||||
|
||||
int strmath(const char *str) {
|
||||
return strmath_rdp(str);
|
||||
}
|
||||
|
||||
#endif //ifdef BSTRING_H
|
||||
@@ -0,0 +1,277 @@
|
||||
#ifdef BSTRING_H
|
||||
|
||||
char chrlower(char c) {
|
||||
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
char chrupper(char c) {
|
||||
return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
int stricmp(const char *dest, const char *src) {
|
||||
while(*dest) {
|
||||
if(chrlower(*dest) != chrlower(*src)) break;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
|
||||
return (int)chrlower(*dest) - (int)chrlower(*src);
|
||||
}
|
||||
|
||||
void strcpy(string &dest, const char *src) {
|
||||
int srclen = strlen(src);
|
||||
dest.reserve(srclen);
|
||||
strcpy(dest(), src);
|
||||
}
|
||||
|
||||
void strcat(string &dest, const char *src) {
|
||||
int srclen = strlen(src);
|
||||
int destlen = strlen(dest);
|
||||
dest.reserve(srclen + destlen);
|
||||
strcat(dest(), src);
|
||||
}
|
||||
|
||||
string substr(const char *src, uint start, uint length) {
|
||||
string dest;
|
||||
if(length == 0) {
|
||||
//copy entire string
|
||||
strcpy(dest, src + start);
|
||||
} else {
|
||||
//copy partial string
|
||||
strlcpy(dest, src + start, length + 1);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* strlower(char *str) {
|
||||
uint i = 0;
|
||||
while(str[i]) {
|
||||
str[i] = chrlower(str[i]);
|
||||
i++;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
char* strupper(char *str) {
|
||||
uint i = 0;
|
||||
while(str[i]) {
|
||||
str[i] = chrupper(str[i]);
|
||||
i++;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
string& strlower(string &str) {
|
||||
strlower(str());
|
||||
return str;
|
||||
}
|
||||
|
||||
string& strupper(string &str) {
|
||||
strupper(str());
|
||||
return str;
|
||||
}
|
||||
|
||||
int strpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl) return -1;
|
||||
for(int i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qstrpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl) return -1;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
uint8 x = str[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
uint8 z = i++;
|
||||
while(str[i] != x && i < ssl) i++;
|
||||
if(i >= ssl) i = z;
|
||||
}
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* strtr(char *dest, const char *before, const char *after) {
|
||||
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
|
||||
if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace
|
||||
for(int i = 0; i < sl; i++) {
|
||||
for(int l = 0; l < bsl; l++) {
|
||||
if(dest[i] == before[l]) {
|
||||
dest[i] = after[l];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
string& strtr(string &dest, const char *before, const char *after) {
|
||||
strtr(dest(), before, after);
|
||||
return dest;
|
||||
}
|
||||
|
||||
bool strbegin(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
return (!memcmp(str, key, ksl));
|
||||
}
|
||||
|
||||
bool stribegin(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
for(int i = 0; i < ksl; i++) {
|
||||
if(str[i] >= 'A' && str[i] <= 'Z') {
|
||||
if(str[i] != key[i] && str[i]+0x20 != key[i])return false;
|
||||
} else if(str[i] >= 'a' && str[i] <= 'z') {
|
||||
if(str[i] != key[i] && str[i]-0x20 != key[i])return false;
|
||||
} else {
|
||||
if(str[i] != key[i])return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strend(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
return (!memcmp(str + ssl - ksl, key, ksl));
|
||||
}
|
||||
|
||||
bool striend(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) {
|
||||
if(str[i] >= 'A' && str[i] <= 'Z') {
|
||||
if(str[i] != key[z] && str[i]+0x20 != key[z])return false;
|
||||
} else if(str[i] >= 'a' && str[i] <= 'z') {
|
||||
if(str[i] != key[z] && str[i]-0x20 != key[z])return false;
|
||||
} else {
|
||||
if(str[i] != key[z])return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint strhex(const char *str) {
|
||||
uint r = 0, m = 0;
|
||||
int i = 0, ssl = strlen(str);
|
||||
uint8 x;
|
||||
bool negate = (str[0] == '-');
|
||||
if(negate)i++;
|
||||
for(; i < ssl; i++) {
|
||||
if(str[i] >= '0' && str[i] <= '9');
|
||||
else if(str[i] >= 'A' && str[i] <= 'F');
|
||||
else if(str[i] >= 'a' && str[i] <= 'f');
|
||||
else break;
|
||||
}
|
||||
for(--i; i >= 0; i--, m += 4) {
|
||||
x = str[i];
|
||||
if(x >= '0' && x <= '9')x -= '0';
|
||||
else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a;
|
||||
else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a;
|
||||
else break;
|
||||
r |= x << m;
|
||||
}
|
||||
return !negate ? r : (uint)-r;
|
||||
}
|
||||
|
||||
uint strdec(const char *str) {
|
||||
uint m = 1;
|
||||
int i = 0, r = 0, ssl = strlen(str);
|
||||
uint8 x;
|
||||
bool negate = (str[0] == '-');
|
||||
if(negate)i++;
|
||||
for(; i < ssl; i++) {
|
||||
if(str[i] >= '0' && str[i] <= '9');
|
||||
else break;
|
||||
}
|
||||
for(--i; i >= 0; i--, m *= 10) {
|
||||
x = str[i];
|
||||
if(x >= '0' && x <= '9')x -= '0';
|
||||
else break;
|
||||
r += x * m;
|
||||
}
|
||||
return !negate ? r : (uint)-r;
|
||||
}
|
||||
|
||||
uint strbin(const char *str) {
|
||||
uint r = 0, m = 0;
|
||||
int i = 0, ssl = strlen(str);
|
||||
uint8 x;
|
||||
bool negate = (str[0] == '-');
|
||||
if(negate)i++;
|
||||
for(; i < ssl; i++) {
|
||||
if(str[i] == '0' || str[i] == '1');
|
||||
else break;
|
||||
}
|
||||
for(--i; i >= 0; i--, m++) {
|
||||
x = str[i];
|
||||
if(str[i] == '0' || str[i] == '1')x -= '0';
|
||||
else break;
|
||||
r |= x << m;
|
||||
}
|
||||
return !negate ? r : (uint)-r;
|
||||
}
|
||||
|
||||
string &utoa(string &str, uint num) {
|
||||
str.reserve(16);
|
||||
sprintf(str(), "%u", num);
|
||||
return str;
|
||||
}
|
||||
|
||||
string &itoa(string &str, uint num) {
|
||||
str.reserve(16);
|
||||
sprintf(str(), "%d", num);
|
||||
return str;
|
||||
}
|
||||
|
||||
string &htoa(string &str, uint num) {
|
||||
str.reserve(16);
|
||||
sprintf(str(), "%x", num);
|
||||
return str;
|
||||
}
|
||||
|
||||
string &btoa(string &str, uint num) {
|
||||
str.reserve(64);
|
||||
|
||||
char *pstr = str();
|
||||
uint mask = 0x80000000;
|
||||
while(mask && (num & mask) == 0)mask >>= 1;
|
||||
while(mask > 1) {
|
||||
*pstr++ = (num & mask) ? '1' : '0';
|
||||
mask >>= 1;
|
||||
}
|
||||
*pstr++ = (num & mask) ? '1' : '0';
|
||||
*pstr = 0;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
bool fread(string &str, const char *filename) {
|
||||
strcpy(str, "");
|
||||
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if(!fp)return false;
|
||||
|
||||
uint size = fsize(fp);
|
||||
char *fdata = (char*)malloc(size + 1);
|
||||
fread(fdata, 1, size, fp);
|
||||
fclose(fp);
|
||||
fdata[size] = 0;
|
||||
strcpy(str, fdata);
|
||||
free(fdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //ifdef BSTRING_H
|
||||
@@ -1,86 +1,88 @@
|
||||
string &replace(string &str, const char *key, const char *token) {
|
||||
int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
|
||||
uint replace_count = 0, size = ssl;
|
||||
char *data;
|
||||
if(ksl > ssl)return str;
|
||||
if(tsl > ksl) { //the new string may be longer than the old string...
|
||||
for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
|
||||
if(!memcmp(str.s + i, key, ksl)) {
|
||||
replace_count++;
|
||||
i += ksl;
|
||||
} else i++;
|
||||
}
|
||||
size = ssl + ((tsl - ksl) * replace_count);
|
||||
str.reserve(size);
|
||||
}
|
||||
data = (char*)malloc(size + 1);
|
||||
for(i = z = 0; i < ssl;) {
|
||||
if(i <= ssl - ksl) {
|
||||
if(!memcmp(str.s + i, key, ksl)) {
|
||||
memcpy(data + z, token, tsl);
|
||||
z += tsl;
|
||||
i += ksl;
|
||||
} else data[z++] = str.s[i++];
|
||||
} else data[z++] = str.s[i++];
|
||||
}
|
||||
data[z] = 0;
|
||||
strcpy(str, data);
|
||||
free(data);
|
||||
return str;
|
||||
}
|
||||
string &replace(string &str, const char *key, const string &token) { return replace(str, key, strptr(token)); }
|
||||
|
||||
string &qreplace(string &str, const char *key, const char *token) {
|
||||
int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
|
||||
uint replace_count = 0, size = ssl;
|
||||
uint8 x;
|
||||
char *data;
|
||||
if(ksl > ssl)return str;
|
||||
if(tsl > ksl) {
|
||||
for(i = 0; i <= ssl - ksl;) {
|
||||
x = str.s[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
l = i;
|
||||
i++;
|
||||
while(str.s[i++] != x) {
|
||||
if(i == ssl) {
|
||||
i = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!memcmp(str.s + i, key, ksl)) {
|
||||
replace_count++;
|
||||
i += ksl;
|
||||
} else i++;
|
||||
}
|
||||
size = ssl + ((tsl - ksl) * replace_count);
|
||||
str.reserve(size);
|
||||
}
|
||||
data = (char*)malloc(size + 1);
|
||||
for(i = z = 0; i < ssl;) {
|
||||
x = str.s[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
l = i++;
|
||||
while(str.s[i] != x && i < ssl)i++;
|
||||
if(i >= ssl)i = l;
|
||||
else {
|
||||
memcpy(data + z, str.s + l, i - l);
|
||||
z += i - l;
|
||||
}
|
||||
}
|
||||
if(i <= ssl - ksl) {
|
||||
if(!memcmp(str.s + i, key, ksl)) {
|
||||
memcpy(data + z, token, tsl);
|
||||
z += tsl;
|
||||
i += ksl;
|
||||
replace_count++;
|
||||
} else data[z++] = str.s[i++];
|
||||
} else data[z++] = str.s[i++];
|
||||
}
|
||||
data[z] = 0;
|
||||
strcpy(str, data);
|
||||
free(data);
|
||||
return str;
|
||||
}
|
||||
string &qreplace(string &str, const char *key, const string &token) { return qreplace(str, key, strptr(token)); }
|
||||
#ifdef BSTRING_H
|
||||
|
||||
string &replace(string &str, const char *key, const char *token) {
|
||||
int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
|
||||
uint replace_count = 0, size = ssl;
|
||||
char *data;
|
||||
if(ksl > ssl)return str;
|
||||
if(tsl > ksl) { //the new string may be longer than the old string...
|
||||
for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
|
||||
if(!memcmp(str() + i, key, ksl)) {
|
||||
replace_count++;
|
||||
i += ksl;
|
||||
} else i++;
|
||||
}
|
||||
size = ssl + ((tsl - ksl) * replace_count);
|
||||
str.reserve(size);
|
||||
}
|
||||
data = (char*)malloc(size + 1);
|
||||
for(i = z = 0; i < ssl;) {
|
||||
if(i <= ssl - ksl) {
|
||||
if(!memcmp(str() + i, key, ksl)) {
|
||||
memcpy(data + z, token, tsl);
|
||||
z += tsl;
|
||||
i += ksl;
|
||||
} else data[z++] = str()[i++];
|
||||
} else data[z++] = str()[i++];
|
||||
}
|
||||
data[z] = 0;
|
||||
strcpy(str, data);
|
||||
free(data);
|
||||
return str;
|
||||
}
|
||||
|
||||
string &qreplace(string &str, const char *key, const char *token) {
|
||||
int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str);
|
||||
uint replace_count = 0, size = ssl;
|
||||
uint8 x;
|
||||
char *data;
|
||||
if(ksl > ssl)return str;
|
||||
if(tsl > ksl) {
|
||||
for(i = 0; i <= ssl - ksl;) {
|
||||
x = str()[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
l = i;
|
||||
i++;
|
||||
while(str()[i++] != x) {
|
||||
if(i == ssl) {
|
||||
i = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!memcmp(str() + i, key, ksl)) {
|
||||
replace_count++;
|
||||
i += ksl;
|
||||
} else i++;
|
||||
}
|
||||
size = ssl + ((tsl - ksl) * replace_count);
|
||||
str.reserve(size);
|
||||
}
|
||||
data = (char*)malloc(size + 1);
|
||||
for(i = z = 0; i < ssl;) {
|
||||
x = str()[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
l = i++;
|
||||
while(str()[i] != x && i < ssl)i++;
|
||||
if(i >= ssl)i = l;
|
||||
else {
|
||||
memcpy(data + z, str() + l, i - l);
|
||||
z += i - l;
|
||||
}
|
||||
}
|
||||
if(i <= ssl - ksl) {
|
||||
if(!memcmp(str() + i, key, ksl)) {
|
||||
memcpy(data + z, token, tsl);
|
||||
z += tsl;
|
||||
i += ksl;
|
||||
replace_count++;
|
||||
} else data[z++] = str()[i++];
|
||||
} else data[z++] = str()[i++];
|
||||
}
|
||||
data[z] = 0;
|
||||
strcpy(str, data);
|
||||
free(data);
|
||||
return str;
|
||||
}
|
||||
|
||||
#endif //ifdef BSTRING_H
|
||||
@@ -1,37 +1,39 @@
|
||||
void split(stringarray &dest, const char *key, const char *src) {
|
||||
dest.reset();
|
||||
|
||||
int ssl = strlen(src), ksl = strlen(key);
|
||||
int lp = 0, split_count = 0;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
if(!memcmp(src + i, key, ksl)) {
|
||||
strlcpy(dest[split_count++], src + lp, i - lp + 1);
|
||||
i += ksl;
|
||||
lp = i;
|
||||
} else i++;
|
||||
}
|
||||
strcpy(dest[split_count++], src + lp);
|
||||
}
|
||||
void split(stringarray &dest, const char *key, const string &src) { split(dest, key, strptr(src)); }
|
||||
|
||||
void qsplit(stringarray &dest, const char *key, const char *src) {
|
||||
dest.reset();
|
||||
|
||||
int z, ssl = strlen(src), ksl = strlen(key);
|
||||
int lp = 0, split_count = 0;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
uint8 x = src[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
z = i++;
|
||||
while(src[i] != x && i < ssl)i++;
|
||||
if(i >= ssl)i = z;
|
||||
}
|
||||
if(!memcmp(src + i, key, ksl)) {
|
||||
strlcpy(dest[split_count++], src + lp, i - lp + 1);
|
||||
i += ksl;
|
||||
lp = i;
|
||||
} else i++;
|
||||
}
|
||||
strcpy(dest[split_count++], src + lp);
|
||||
}
|
||||
void qsplit(stringarray &dest, const char *key, const string &src) { qsplit(dest, key, strptr(src)); }
|
||||
#ifdef BSTRING_H
|
||||
|
||||
void split(lstring &dest, const char *key, const char *src) {
|
||||
dest.reset();
|
||||
|
||||
int ssl = strlen(src), ksl = strlen(key);
|
||||
int lp = 0, split_count = 0;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
if(!memcmp(src + i, key, ksl)) {
|
||||
strlcpy(dest[split_count++], src + lp, i - lp + 1);
|
||||
i += ksl;
|
||||
lp = i;
|
||||
} else i++;
|
||||
}
|
||||
strcpy(dest[split_count++], src + lp);
|
||||
}
|
||||
|
||||
void qsplit(lstring &dest, const char *key, const char *src) {
|
||||
dest.reset();
|
||||
|
||||
int z, ssl = strlen(src), ksl = strlen(key);
|
||||
int lp = 0, split_count = 0;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
uint8 x = src[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
z = i++;
|
||||
while(src[i] != x && i < ssl)i++;
|
||||
if(i >= ssl)i = z;
|
||||
}
|
||||
if(!memcmp(src + i, key, ksl)) {
|
||||
strlcpy(dest[split_count++], src + lp, i - lp + 1);
|
||||
i += ksl;
|
||||
lp = i;
|
||||
} else i++;
|
||||
}
|
||||
strcpy(dest[split_count++], src + lp);
|
||||
}
|
||||
|
||||
#endif //ifdef BSTRING_H
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifdef BSTRING_H
|
||||
|
||||
uint strlcpy(char *dest, const char *src, uint length) {
|
||||
uint srclen = strlen(src);
|
||||
length--;
|
||||
if(length > srclen) length = srclen;
|
||||
memcpy(dest, src, length);
|
||||
dest[length] = 0;
|
||||
return srclen;
|
||||
}
|
||||
|
||||
uint strlcat(char *dest, const char *src, uint length) {
|
||||
uint destlen = strlen(dest), srclen = strlen(src);
|
||||
length--;
|
||||
if(length > destlen + srclen) length = destlen + srclen;
|
||||
memcpy(dest + destlen, src, length - destlen);
|
||||
dest[length] = 0;
|
||||
return destlen + srclen;
|
||||
}
|
||||
|
||||
uint strlcpy(string &dest, const char *src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcpy(dest(), src, length);
|
||||
}
|
||||
|
||||
uint strlcat(string &dest, const char *src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcat(dest(), src, length);
|
||||
}
|
||||
|
||||
#endif //ifdef BSTRING_H
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifdef BSTRING_H
|
||||
|
||||
char* ltrim(char *str, const char *key) {
|
||||
if(!key || !*key) return str;
|
||||
while(strbegin(str, key)) {
|
||||
string temp = str;
|
||||
strcpy(str, temp() + strlen(key));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
char* rtrim(char *str, const char *key) {
|
||||
if(!key || !*key) return str;
|
||||
while(strend(str, key)) {
|
||||
str[strlen(str) - strlen(key)] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
char* trim(char *str, const char *key) {
|
||||
return ltrim(rtrim(str, key), key);
|
||||
}
|
||||
|
||||
string& ltrim(string &str, const char *key) {
|
||||
ltrim(str(), key);
|
||||
return str;
|
||||
}
|
||||
|
||||
string& rtrim(string &str, const char *key) {
|
||||
rtrim(str(), key);
|
||||
return str;
|
||||
}
|
||||
|
||||
string& trim(string &str, const char *key) {
|
||||
trim(str(), key);
|
||||
return str;
|
||||
}
|
||||
|
||||
#endif //ifdef BSTRING_H
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
libvector : version 0.05 ~byuu (2006-12-16)
|
||||
bvector : version 0.05 ~byuu (2006-12-16)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
/*****
|
||||
@@ -64,8 +65,8 @@
|
||||
* and speed is less critical.
|
||||
*****/
|
||||
|
||||
#ifndef LIBVECTOR_H
|
||||
#define LIBVECTOR_H
|
||||
#ifndef BVECTOR_H
|
||||
#define BVECTOR_H
|
||||
|
||||
template<typename T> class linear_vector {
|
||||
protected:
|
||||
@@ -204,4 +205,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif //ifndef BVECTOR_H
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
libarray : version 0.09 ~byuu (2007-03-06)
|
||||
*/
|
||||
|
||||
#ifndef LIBARRAY_H
|
||||
#define LIBARRAY_H
|
||||
|
||||
template<typename T> class array {
|
||||
protected:
|
||||
T *pool;
|
||||
uint poolsize, buffersize;
|
||||
|
||||
protected:
|
||||
uint findsize(uint size) {
|
||||
if(size <= 0x100) { return 0x100; }
|
||||
if(size <= 0x400) { return 0x400; }
|
||||
if(size <= 0x1000) { return 0x1000; }
|
||||
if(size <= 0x4000) { return 0x4000; }
|
||||
if(size <= 0x10000) { return 0x10000; }
|
||||
if(size <= 0x40000) { return 0x40000; }
|
||||
if(size <= 0x100000) { return 0x100000; }
|
||||
|
||||
return (size + 0x100000) & ~0xfffff;
|
||||
}
|
||||
|
||||
public:
|
||||
uint size() { return buffersize; }
|
||||
uint capacity() { return poolsize; }
|
||||
|
||||
void reset() {
|
||||
safe_free(pool);
|
||||
poolsize = 0;
|
||||
buffersize = 0;
|
||||
}
|
||||
|
||||
void reserve(uint size) {
|
||||
if(size == poolsize)return;
|
||||
|
||||
if(size < poolsize) {
|
||||
buffersize = size;
|
||||
}
|
||||
|
||||
pool = (T*)realloc(pool, sizeof(T) * size);
|
||||
poolsize = size;
|
||||
}
|
||||
|
||||
T *get(uint size = 0) {
|
||||
if(size > buffersize)resize(size);
|
||||
if(size > buffersize)throw "array[] out of bounds";
|
||||
return pool;
|
||||
}
|
||||
|
||||
void clear() { memset(pool, 0, sizeof(T) * buffersize); }
|
||||
|
||||
void resize(uint size) {
|
||||
reserve(findsize(size));
|
||||
buffersize = size;
|
||||
}
|
||||
|
||||
array() {
|
||||
pool = 0;
|
||||
poolsize = 0;
|
||||
buffersize = 0;
|
||||
}
|
||||
|
||||
~array() { reset(); }
|
||||
|
||||
array &operator=(array &source) {
|
||||
safe_free(pool);
|
||||
buffersize = source.buffersize;
|
||||
poolsize = source.poolsize;
|
||||
//allocate entire pool size ...
|
||||
pool = (T*)realloc(pool, sizeof(T) * poolsize);
|
||||
//... but only copy used pool objects
|
||||
memcpy(pool, source.pool, sizeof(T) * buffersize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline T &operator[](int index) {
|
||||
if(index >= buffersize)resize(index + 1);
|
||||
if(index >= buffersize)throw "array[] out of bounds";
|
||||
return pool[index];
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
libco
|
||||
version: 0.11 (2007-12-11)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#if defined(__GNUC__)
|
||||
#define calltype __attribute__((fastcall))
|
||||
#elif defined(_MSC_VER)
|
||||
#define calltype __fastcall
|
||||
#endif
|
||||
#else
|
||||
#define calltype
|
||||
#endif
|
||||
|
||||
typedef void* cothread_t;
|
||||
|
||||
cothread_t calltype co_active();
|
||||
cothread_t calltype co_create(unsigned int heapsize, void (*coentry)());
|
||||
void calltype co_delete(cothread_t cothread);
|
||||
void calltype co_switch(cothread_t cothread);
|
||||
|
||||
#undef calltype
|
||||
|
||||
#ifdef __cplusplus
|
||||
} //extern "C"
|
||||
#endif
|
||||
|
||||
#endif //ifndef LIBCO_H
|
||||
@@ -0,0 +1,478 @@
|
||||
;*****
|
||||
;libco.ppc (2007-11-29)
|
||||
;author: Vas Crabb
|
||||
;license: public domain
|
||||
;
|
||||
;cross-platform PowerPC implementation of libco
|
||||
;special thanks to byuu for writing the original version
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- gcc; mac os x; ppc
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- GPR1, GPR13 - GPR31
|
||||
;- FPR14 - FPR31
|
||||
;- V20 - V31
|
||||
;- VRSAVE, CR2 - CR4
|
||||
;
|
||||
;[volatile registers]
|
||||
;- GPR0, GPR2 - GPR12
|
||||
;- FPR0 - FPR13
|
||||
;- V0 - V19
|
||||
;- LR, CTR, XER, CR0, CR1, CR5 - CR7
|
||||
;*****
|
||||
|
||||
|
||||
;Declare some target-specific stuff
|
||||
|
||||
.section __TEXT,__text,regular,pure_instructions
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.machine ppc
|
||||
|
||||
|
||||
;Constants
|
||||
|
||||
.cstring
|
||||
.align 2
|
||||
|
||||
_sysctl_altivec:
|
||||
.ascii "hw.optional.altivec\0"
|
||||
|
||||
|
||||
;Declare space for variables
|
||||
|
||||
.lcomm _co_environ,4,2 ;bit 0 = initialised, bit 1 = have Altivec/VMX
|
||||
.lcomm _co_primary_buffer,1024,2 ;buffer (will be zeroed by loader)
|
||||
|
||||
.data
|
||||
.align 2
|
||||
|
||||
_co_active_context:
|
||||
.long _co_primary_buffer
|
||||
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
|
||||
;Declare exported names
|
||||
|
||||
.globl _co_active
|
||||
.globl _co_create
|
||||
.globl _co_delete
|
||||
.globl _co_switch
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_active();
|
||||
;return = GPR3
|
||||
;*****
|
||||
|
||||
_co_active:
|
||||
mflr r0 ;GPR0 = return address
|
||||
bcl 20,31,L_co_active$spb
|
||||
L_co_active$spb:
|
||||
mflr r2 ;GPR2 set for position-independance
|
||||
addis r3,r2,ha16(_co_active_context-L_co_active$spb) ;get value in GPR3
|
||||
lwz r3,lo16(_co_active_context-L_co_active$spb)(r3)
|
||||
mtlr r0 ;LR = return address
|
||||
blr ;return
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
;GPR3 = heapsize
|
||||
;GPR4 = coentry
|
||||
;return = GPR3
|
||||
;*****
|
||||
|
||||
_co_create:
|
||||
mflr r0 ;GPR0 = return address
|
||||
stmw r30,-8(r1) ;save GPR30 and GPR31
|
||||
stw r0,8(r1) ;save return address
|
||||
stwu r1,-(2*4+16+24)(r1) ;allocate 16 bytes for locals/parameters
|
||||
|
||||
;create heap space (stack + register storage)
|
||||
addi r31,r3,1024-24 ;subtract space for linkage
|
||||
mr r30,r4 ;GPR30 = coentry
|
||||
addi r3,r3,1024 ;allocate extra memory for contextual info
|
||||
bl L_malloc$stub ;GPR3 = malloc(heapsize + 1024)
|
||||
add r4,r3,r31 ;GPR4 points to top-of-stack
|
||||
rlwinm r5,r4,0,0,27 ;force 16-byte alignment
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
stw r30,8(r5) ;store entry point
|
||||
addi r6,0,2+19+18*2+12*4+1 ;clear for CR, old GPR1, 19 GPRs, 18 FPRs, 12 VRs, VRSAVE
|
||||
addi r0,0,0
|
||||
addi r7,0,4 ;start at 4(GPR5)
|
||||
mtctr r6
|
||||
L_co_create$clear_loop:
|
||||
stwx r0,r5,r7 ;clear a word
|
||||
addi r7,r7,-4 ;increment pointer
|
||||
bdnz L_co_create$clear_loop ;loop
|
||||
stwu r5,-448(r5) ;store top of stack
|
||||
|
||||
;initialize context memory heap and return
|
||||
stw r5,0(r3) ;*cothread_t = stack heap pointer (GPR1)
|
||||
lwz r1,0(r1) ;deallocate stack frame
|
||||
lwz r8,8(r1) ;fetch return address
|
||||
lmw r30,-8(r1) ;restore GPR30 and GPR31
|
||||
mtlr r8 ;return address in LR
|
||||
blr ;return
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" void co_delete(cothread_t cothread);
|
||||
;GPR3 = cothread
|
||||
;*****
|
||||
|
||||
_co_delete:
|
||||
b L_free$stub ;free(GPR3)
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" void co_switch(cothread_t cothread);
|
||||
;GPR3 = cothread
|
||||
;*****
|
||||
;
|
||||
;Frame looks like:
|
||||
;
|
||||
;Old New Value
|
||||
; 8(r1) 456(r1) Saved LR
|
||||
; 4(r1) 452(r1) Saved CR
|
||||
; 0(r1) 448(r1) Old GPR1
|
||||
; -4(r1) 444(r1) Saved GPR31
|
||||
; -8(r1) 440(r1) Saved GPR30
|
||||
;... ... ...
|
||||
; -72(r1) 376(r1) Saved GPR14
|
||||
; -76(r1) 372(r1) Saved GPR13
|
||||
; -80(r1) 368(r1) Saved VRSAVE
|
||||
; -84(r1) 364(r1) +++
|
||||
; -88(r1) 360(r1) Saved FPR31
|
||||
; -92(r1) 356(r1) +++
|
||||
; -96(r1) 352(r1) Saved FPR30
|
||||
;... ... ...
|
||||
;-212(r1) 236(r1) +++
|
||||
;-216(r1) 232(r1) Saved FPR15
|
||||
;-220(r1) 228(r1) +++
|
||||
;-224(r1) 224(r1) Saved FPR14
|
||||
;-228(r1) 220(r1) +++ value
|
||||
;-232(r1) 216(r1) +++ len
|
||||
;-236(r1) 212(r1) +++
|
||||
;-240(r1) 208(r1) Saved VR31
|
||||
;-244(r1) 204(r1) +++
|
||||
;-248(r1) 200(r1) +++
|
||||
;-252(r1) 196(r1) +++
|
||||
;-256(r1) 192(r1) Saved VR30
|
||||
;... ... ...
|
||||
;-388(r1) 60(r1) +++
|
||||
;-392(r1) 56(r1) +++
|
||||
;-396(r1) 52(r1) +++
|
||||
;-400(r1) 48(r1) Saved VR21
|
||||
;-404(r1) 44(r1) +++
|
||||
;-408(r1) 40(r1) +++ Param 5 (GPR7)
|
||||
;-412(r1) 36(r1) +++ Param 4 (GPR6)
|
||||
;-416(r1) 32(r1) Saved VR20 Param 3 (GPR5)
|
||||
;-420(r1) 28(r1) - Param 2 (GPR4)
|
||||
;-424(r1) 24(r1) - Param 1 (GPR3)
|
||||
;-428(r1) 20(r1) - Reserved
|
||||
;-432(r1) 16(r1) - Reserved
|
||||
;-436(r1) 12(r1) - Reserved
|
||||
;-440(r1) 8(r1) - New LR
|
||||
;-444(r1) 4(r1) - New CR
|
||||
;-448(r1) 0(r1) Saved GPR1
|
||||
|
||||
|
||||
_co_switch:
|
||||
stmw r13,-76(r1) ;save preserved GPRs
|
||||
stfd f14,-224(r1) ;save preserved FPRs
|
||||
stfd f15,-216(r1)
|
||||
stfd f16,-208(r1)
|
||||
stfd f17,-200(r1)
|
||||
stfd f18,-192(r1)
|
||||
stfd f19,-184(r1)
|
||||
stfd f20,-176(r1)
|
||||
stfd f21,-168(r1)
|
||||
stfd f22,-160(r1)
|
||||
stfd f23,-152(r1)
|
||||
stfd f24,-144(r1)
|
||||
stfd f25,-136(r1)
|
||||
stfd f26,-128(r1)
|
||||
stfd f27,-120(r1)
|
||||
stfd f28,-112(r1)
|
||||
stfd f29,-104(r1)
|
||||
stfd f30,-96(r1)
|
||||
stfd f31,-88(r1)
|
||||
mflr r0 ;save return address
|
||||
stw r0,8(r1)
|
||||
mfcr r2 ;save condition codes
|
||||
stw r2,4(r1)
|
||||
stwu r1,-448(r1) ;create stack frame (save 19 GPRs, 18 FRPs, 12 VRs, VRSAVE)
|
||||
|
||||
mr r30,r3 ;save new context pointer
|
||||
bcl 20,31,L_co_switch$spb ;get address of co_active_context
|
||||
L_co_switch$spb:
|
||||
mflr r31
|
||||
|
||||
addis r29,r31,ha16(_co_environ-L_co_switch$spb) ;get environment flags
|
||||
lwz r8,lo16(_co_environ-L_co_switch$spb)(r29)
|
||||
andis. r9,r8,0x8000 ;is it initialised?
|
||||
bne+ L_co_switch$initialised
|
||||
|
||||
addi r0,0,4 ;len = sizeof(int)
|
||||
stw r0,216(r1)
|
||||
addis r3,r31,ha16(_sysctl_altivec-L_co_switch$spb) ;GPR3 = "hw.optional.altivec"
|
||||
addi r3,r3,lo16(_sysctl_altivec-L_co_switch$spb)
|
||||
addi r4,r1,220 ;GPR4 = &value
|
||||
addi r5,r1,216 ;GPR5 = &len
|
||||
addi r6,0,0 ;newp = 0
|
||||
addi r7,0,0 ;newlen = 0
|
||||
bl L_sysctlbyname$stub ;call sysctlbyname
|
||||
lwz r2,220(r1) ;fetch result
|
||||
addis r8,0,0x8000 ;set initialised bit
|
||||
cmpwi cr5,r3,0 ;assume error means not present
|
||||
cmpwi cr6,r2,0 ;test result
|
||||
blt- cr5,L_co_switch$store_environ
|
||||
beq cr6,L_co_switch$store_environ
|
||||
oris r8,r8,0x4000 ;set the flag to say we have it!
|
||||
L_co_switch$store_environ:
|
||||
stw r8,lo16(_co_environ-L_co_switch$spb)(r29) ;store environment flags
|
||||
L_co_switch$initialised:
|
||||
|
||||
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
|
||||
beq L_co_switch$save_no_vmx
|
||||
mfspr r11,256 ;save VRSAVE
|
||||
andi. r0,r11,0x0FFF ;short-circuit if it's zero
|
||||
stw r11,368(r1)
|
||||
beq L_co_switch$save_no_vmx
|
||||
andi. r0,r11,0x0800 ;check bit 20
|
||||
addi r2,0,32 ;starting index
|
||||
beq L_co_switch$save_skip_vr20
|
||||
stvx v20,r1,r2 ;save VR20
|
||||
L_co_switch$save_skip_vr20:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0400 ;check bit 21
|
||||
beq L_co_switch$save_skip_vr21
|
||||
stvx v21,r1,r2 ;save VR21
|
||||
L_co_switch$save_skip_vr21:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0200 ;check bit 22
|
||||
beq L_co_switch$save_skip_vr22
|
||||
stvx v22,r1,r2 ;save VR22
|
||||
L_co_switch$save_skip_vr22:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0100 ;check bit 23
|
||||
beq L_co_switch$save_skip_vr23
|
||||
stvx v23,r1,r2 ;save VR23
|
||||
L_co_switch$save_skip_vr23:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0080 ;check bit 24
|
||||
beq L_co_switch$save_skip_vr24
|
||||
stvx v24,r1,r2 ;save VR24
|
||||
L_co_switch$save_skip_vr24:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0040 ;check bit 25
|
||||
beq L_co_switch$save_skip_vr25
|
||||
stvx v25,r1,r2 ;save VR25
|
||||
L_co_switch$save_skip_vr25:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0020 ;check bit 26
|
||||
beq L_co_switch$save_skip_vr26
|
||||
stvx v26,r1,r2 ;save VR26
|
||||
L_co_switch$save_skip_vr26:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0010 ;check bit 27
|
||||
beq L_co_switch$save_skip_vr27
|
||||
stvx v27,r1,r2 ;save VR27
|
||||
L_co_switch$save_skip_vr27:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0008 ;check bit 28
|
||||
beq L_co_switch$save_skip_vr28
|
||||
stvx v28,r1,r2 ;save VR28
|
||||
L_co_switch$save_skip_vr28:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0004 ;check bit 29
|
||||
beq L_co_switch$save_skip_vr29
|
||||
stvx v29,r1,r2 ;save VR29
|
||||
L_co_switch$save_skip_vr29:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0002 ;check bit 30
|
||||
beq L_co_switch$save_skip_vr30
|
||||
stvx v30,r1,r2 ;save VR30
|
||||
L_co_switch$save_skip_vr30:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0001 ;check bit 31
|
||||
beq L_co_switch$save_skip_vr31
|
||||
stvx v31,r1,r2 ;save VR31
|
||||
L_co_switch$save_skip_vr31:
|
||||
L_co_switch$save_no_vmx:
|
||||
|
||||
addis r4,r31,ha16(_co_active_context-L_co_switch$spb) ;save current context
|
||||
lwz r5,lo16(_co_active_context-L_co_switch$spb)(r4)
|
||||
stw r30,lo16(_co_active_context-L_co_switch$spb)(r4);set new context
|
||||
stw r1,0(r5) ;save current stack pointer
|
||||
lwz r1,0(r30) ;get new stack pointer
|
||||
|
||||
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
|
||||
beq L_co_switch$restore_no_vmx
|
||||
lwz r11,368(r1) ;restore VRSAVE
|
||||
andi. r0,r11,0x0FFF ;short-circuit if it's zero
|
||||
mtspr 256,r11
|
||||
beq L_co_switch$restore_no_vmx
|
||||
andi. r0,r11,0x0800 ;check bit 20
|
||||
addi r2,0,32 ;starting index
|
||||
beq L_co_switch$restore_skip_vr20
|
||||
lvx v20,r1,r2 ;restore VR20
|
||||
L_co_switch$restore_skip_vr20:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0400 ;check bit 21
|
||||
beq L_co_switch$restore_skip_vr21
|
||||
lvx v21,r1,r2 ;restore VR21
|
||||
L_co_switch$restore_skip_vr21:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0200 ;check bit 22
|
||||
beq L_co_switch$restore_skip_vr22
|
||||
lvx v22,r1,r2 ;restore VR22
|
||||
L_co_switch$restore_skip_vr22:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0100 ;check bit 23
|
||||
beq L_co_switch$restore_skip_vr23
|
||||
lvx v23,r1,r2 ;restore VR23
|
||||
L_co_switch$restore_skip_vr23:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0080 ;check bit 24
|
||||
beq L_co_switch$restore_skip_vr24
|
||||
lvx v24,r1,r2 ;restore VR24
|
||||
L_co_switch$restore_skip_vr24:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0040 ;check bit 25
|
||||
beq L_co_switch$restore_skip_vr25
|
||||
lvx v25,r1,r2 ;restore VR25
|
||||
L_co_switch$restore_skip_vr25:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0020 ;check bit 26
|
||||
beq L_co_switch$restore_skip_vr26
|
||||
lvx v26,r1,r2 ;restore VR26
|
||||
L_co_switch$restore_skip_vr26:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0010 ;check bit 27
|
||||
beq L_co_switch$restore_skip_vr27
|
||||
lvx v27,r1,r2 ;restore VR27
|
||||
L_co_switch$restore_skip_vr27:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0008 ;check bit 28
|
||||
beq L_co_switch$restore_skip_vr28
|
||||
lvx v28,r1,r2 ;restore VR28
|
||||
L_co_switch$restore_skip_vr28:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0004 ;check bit 29
|
||||
beq L_co_switch$restore_skip_vr29
|
||||
lvx v29,r1,r2 ;restore VR29
|
||||
L_co_switch$restore_skip_vr29:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0002 ;check bit 30
|
||||
beq L_co_switch$restore_skip_vr30
|
||||
lvx v30,r1,r2 ;restore VR30
|
||||
L_co_switch$restore_skip_vr30:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0001 ;check bit 31
|
||||
beq L_co_switch$restore_skip_vr31
|
||||
lvx v31,r1,r2 ;restore VR31
|
||||
L_co_switch$restore_skip_vr31:
|
||||
L_co_switch$restore_no_vmx:
|
||||
|
||||
lwz r1,0(r1) ;deallocate stack frame
|
||||
lwz r6,8(r1) ;return address in GPR6
|
||||
lwz r7,4(r1) ;condition codes in GPR7
|
||||
addi r0,0,0 ;make thread main crash if it returns
|
||||
lmw r13,-76(r1) ;restore preserved GPRs
|
||||
lfd f14,-224(r1) ;restore preserved FPRs
|
||||
lfd f15,-216(r1)
|
||||
lfd f16,-208(r1)
|
||||
lfd f17,-200(r1)
|
||||
lfd f18,-192(r1)
|
||||
lfd f19,-184(r1)
|
||||
lfd f20,-176(r1)
|
||||
lfd f21,-168(r1)
|
||||
lfd f22,-160(r1)
|
||||
lfd f23,-152(r1)
|
||||
lfd f24,-144(r1)
|
||||
lfd f25,-136(r1)
|
||||
lfd f26,-128(r1)
|
||||
lfd f27,-120(r1)
|
||||
lfd f28,-112(r1)
|
||||
lfd f29,-104(r1)
|
||||
lfd f30,-96(r1)
|
||||
lfd f31,-88(r1)
|
||||
mtlr r0
|
||||
mtctr r6 ;restore return address
|
||||
mtcrf 32,r7 ;restore preserved condition codes
|
||||
mtcrf 16,r7
|
||||
mtcrf 8,r7
|
||||
bctr ;return
|
||||
|
||||
|
||||
|
||||
;Import external functions
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align 5
|
||||
L_malloc$stub:
|
||||
.indirect_symbol _malloc
|
||||
mflr r0
|
||||
bcl 20,31,L_malloc$spb
|
||||
L_malloc$spb:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_malloc$lazy_ptr-L_malloc$spb)
|
||||
mtlr r0
|
||||
lwzu r12,lo16(L_malloc$lazy_ptr-L_malloc$spb)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_malloc$lazy_ptr:
|
||||
.indirect_symbol _malloc
|
||||
.long dyld_stub_binding_helper
|
||||
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align 5
|
||||
L_free$stub:
|
||||
.indirect_symbol _free
|
||||
mflr r0
|
||||
bcl 20,31,L_free$spb
|
||||
L_free$spb:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_free$lazy_ptr-L_free$spb)
|
||||
mtlr r0
|
||||
lwzu r12,lo16(L_free$lazy_ptr-L_free$spb)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_free$lazy_ptr:
|
||||
.indirect_symbol _free
|
||||
.long dyld_stub_binding_helper
|
||||
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align 5
|
||||
L_sysctlbyname$stub:
|
||||
.indirect_symbol _sysctlbyname
|
||||
mflr r0
|
||||
bcl 20,31,L_sysctlbyname$spb
|
||||
L_sysctlbyname$spb:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)
|
||||
mtlr r0
|
||||
lwzu r12,lo16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_sysctlbyname$lazy_ptr:
|
||||
.indirect_symbol _sysctlbyname
|
||||
.long dyld_stub_binding_helper
|
||||
|
||||
|
||||
;This needs to be here!
|
||||
|
||||
.subsections_via_symbols
|
||||
|
||||
@@ -0,0 +1,513 @@
|
||||
;*****
|
||||
;libco.ppc64 (2007-12-05)
|
||||
;author: Vas Crabb
|
||||
;license: public domain
|
||||
;
|
||||
;cross-platform 64-bit PowerPC implementation of libco
|
||||
;special thanks to byuu for writing the original version
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- gcc; mac os x; ppc64
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- GPR1, GPR13 - GPR31
|
||||
;- FPR14 - FPR31
|
||||
;- V20 - V31
|
||||
;- VRSAVE, CR2 - CR4
|
||||
;
|
||||
;[volatile registers]
|
||||
;- GPR0, GPR2 - GPR12
|
||||
;- FPR0 - FPR13
|
||||
;- V0 - V19
|
||||
;- LR, CTR, XER, CR0, CR1, CR5 - CR7
|
||||
;*****
|
||||
|
||||
|
||||
;Declare some target-specific stuff
|
||||
|
||||
.section __TEXT,__text,regular,pure_instructions
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.machine ppc64
|
||||
|
||||
|
||||
;Constants
|
||||
|
||||
.cstring
|
||||
.align 3
|
||||
|
||||
_sysctl_altivec:
|
||||
.ascii "hw.optional.altivec\0"
|
||||
|
||||
|
||||
;Declare space for variables
|
||||
|
||||
.lcomm _co_environ,4,2 ;bit 0 = initialised, bit 1 = have Altivec/VMX
|
||||
.lcomm _co_primary_buffer,1024,3 ;buffer (will be zeroed by loader)
|
||||
|
||||
.data
|
||||
.align 3
|
||||
|
||||
_co_active_context:
|
||||
.quad _co_primary_buffer
|
||||
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
|
||||
;Declare exported names
|
||||
|
||||
.globl _co_active
|
||||
.globl _co_create
|
||||
.globl _co_delete
|
||||
.globl _co_switch
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_active();
|
||||
;return = GPR3
|
||||
;*****
|
||||
|
||||
_co_active:
|
||||
mflr r0 ;GPR0 = return address
|
||||
bcl 20,31,L_co_active$spb
|
||||
L_co_active$spb:
|
||||
mflr r2 ;GPR2 set for position-independance
|
||||
addis r3,r2,ha16(_co_active_context-L_co_active$spb) ;get value in GPR3
|
||||
ld r3,lo16(_co_active_context-L_co_active$spb)(r3)
|
||||
mtlr r0 ;LR = return address
|
||||
blr ;return
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
;GPR3 = heapsize
|
||||
;GPR4 = coentry
|
||||
;return = GPR3
|
||||
;*****
|
||||
|
||||
_co_create:
|
||||
mflr r0 ;GPR0 = return address
|
||||
std r30,-16(r1) ;save GPR30 and GPR31
|
||||
std r31,-8(r1)
|
||||
std r0,16(r1) ;save return address
|
||||
stdu r1,-(2*8+16+48)(r1) ;allocate 16 bytes for locals/parameters
|
||||
|
||||
;create heap space (stack + register storage)
|
||||
addi r31,r3,1024-48 ;subtract space for linkage
|
||||
mr r30,r4 ;GPR30 = coentry
|
||||
addi r3,r3,1024 ;allocate extra memory for contextual info
|
||||
bl L_malloc$stub ;GPR3 = malloc(heapsize + 1024)
|
||||
add r4,r3,r31 ;GPR4 points to top-of-stack
|
||||
rldicr r5,r4,0,59 ;force 16-byte alignment
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
std r30,16(r5) ;store entry point
|
||||
addi r6,0,2+19+18+12*2+1 ;clear for CR, old GPR1, 19 GPRs, 18 FPRs, 12 VRs, VRSAVE
|
||||
addi r0,0,0
|
||||
addi r7,0,8 ;start at 8(GPR5)
|
||||
mtctr r6
|
||||
L_co_create$clear_loop:
|
||||
stdx r0,r5,r7 ;clear a double
|
||||
addi r7,r7,-8 ;increment pointer
|
||||
bdnz L_co_create$clear_loop ;loop
|
||||
stdu r5,-544(r5) ;store top of stack
|
||||
|
||||
;initialize context memory heap and return
|
||||
addis r9,0,0x8000 ;GPR13 not set (system TLS)
|
||||
std r5,0(r3) ;*cothread_t = stack heap pointer (GPR1)
|
||||
stw r9,8(r3) ;this is a flag word
|
||||
ld r1,0(r1) ;deallocate stack frame
|
||||
ld r8,16(r1) ;fetch return address
|
||||
ld r30,-16(r1) ;restore GPR30 and GPR31
|
||||
ld r31,-8(r1)
|
||||
mtlr r8 ;return address in LR
|
||||
blr ;return
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" void co_delete(cothread_t cothread);
|
||||
;GPR3 = cothread
|
||||
;*****
|
||||
|
||||
_co_delete:
|
||||
b L_free$stub ;free(GPR3)
|
||||
|
||||
|
||||
;*****
|
||||
;extern "C" void co_switch(cothread_t cothread);
|
||||
;GPR3 = cothread
|
||||
;*****
|
||||
;
|
||||
;Frame looks like:
|
||||
;
|
||||
;Old New Value
|
||||
; 16(r1) 560(r1) Saved LR
|
||||
; 8(r1) 552(r1) Saved CR
|
||||
; 0(r1) 544(r1) Old GPR1
|
||||
; -8(r1) 536(r1) Saved GPR31
|
||||
; -16(r1) 528(r1) Saved GPR30
|
||||
;... ... ...
|
||||
;-144(r1) 400(r1) Saved GPR14
|
||||
;-152(r1) 392(r1) Saved GPR13
|
||||
;-160(r1) 384(r1) Saved FPR31
|
||||
;-168(r1) 376(r1) Saved FPR30
|
||||
;... ... ...
|
||||
;-288(r1) 256(r1) Saved FPR15
|
||||
;-296(r1) 248(r1) Saved FPR14
|
||||
;-304(r1) 240(r1) Saved VRSAVE
|
||||
;-312(r1) 232(r1) +++ value
|
||||
;-320(r1) 224(r1) Saved VR31 len
|
||||
;-328(r1) 216(r1) +++
|
||||
;-336(r1) 208(r1) Saved VR30
|
||||
;... ... ...
|
||||
;-456(r1) 88(r1) +++
|
||||
;-464(r1) 80(r1) Saved VR22 Param 5 (GPR7)
|
||||
;-472(r1) 72(r1) +++ Param 4 (GPR6)
|
||||
;-480(r1) 64(r1) Saved VR21 Param 3 (GPR5)
|
||||
;-488(r1) 56(r1) +++ Param 2 (GPR4)
|
||||
;-496(r1) 48(r1) Saved VR20 Param 1 (GPR3)
|
||||
;-504(r1) 40(r1) - Reserved
|
||||
;-512(r1) 32(r1) - Reserved
|
||||
;-520(r1) 24(r1) - Reserved
|
||||
;-528(r1) 16(r1) - New LR
|
||||
;-536(r1) 8(r1) - New CR
|
||||
;-544(r1) 0(r1) Saved GPR1
|
||||
|
||||
|
||||
_co_switch:
|
||||
std r13,-152(r1) ;save preserved GPRs
|
||||
std r14,-144(r1)
|
||||
std r15,-136(r1)
|
||||
std r16,-128(r1)
|
||||
std r17,-120(r1)
|
||||
std r18,-112(r1)
|
||||
std r19,-104(r1)
|
||||
std r20,-96(r1)
|
||||
std r21,-88(r1)
|
||||
std r22,-80(r1)
|
||||
std r23,-72(r1)
|
||||
std r24,-64(r1)
|
||||
std r25,-56(r1)
|
||||
std r26,-48(r1)
|
||||
std r27,-40(r1)
|
||||
std r28,-32(r1)
|
||||
std r29,-24(r1)
|
||||
std r30,-16(r1)
|
||||
std r31,-8(r1)
|
||||
mflr r0 ;save return address
|
||||
std r0,16(r1)
|
||||
mfcr r2 ;save condition codes
|
||||
stw r2,8(r1)
|
||||
stdu r1,-544(r1) ;create stack frame (save 19 GPRs, 18 FRPs, 12 VRs, VRSAVE)
|
||||
stfd f14,248(r1) ;save preserved FPRs
|
||||
stfd f15,256(r1)
|
||||
stfd f16,264(r1)
|
||||
stfd f17,272(r1)
|
||||
stfd f18,280(r1)
|
||||
stfd f19,288(r1)
|
||||
stfd f20,296(r1)
|
||||
stfd f21,304(r1)
|
||||
stfd f22,312(r1)
|
||||
stfd f23,320(r1)
|
||||
stfd f24,328(r1)
|
||||
stfd f25,336(r1)
|
||||
stfd f26,344(r1)
|
||||
stfd f27,352(r1)
|
||||
stfd f28,360(r1)
|
||||
stfd f29,368(r1)
|
||||
stfd f30,376(r1)
|
||||
stfd f31,384(r1)
|
||||
|
||||
mr r30,r3 ;save new context pointer
|
||||
bcl 20,31,L_co_switch$spb ;get address of co_active_context
|
||||
L_co_switch$spb:
|
||||
mflr r31
|
||||
|
||||
addis r29,r31,ha16(_co_environ-L_co_switch$spb) ;get environment flags
|
||||
lwz r8,lo16(_co_environ-L_co_switch$spb)(r29)
|
||||
andis. r9,r8,0x8000 ;is it initialised?
|
||||
bne+ L_co_switch$initialised
|
||||
|
||||
addi r0,0,4 ;len = sizeof(int)
|
||||
std r0,224(r1)
|
||||
addis r3,r31,ha16(_sysctl_altivec-L_co_switch$spb) ;GPR3 = "hw.optional.altivec"
|
||||
addi r3,r3,lo16(_sysctl_altivec-L_co_switch$spb)
|
||||
addi r4,r1,232 ;GPR4 = &value
|
||||
addi r5,r1,224 ;GPR5 = &len
|
||||
addi r6,0,0 ;newp = 0
|
||||
addi r7,0,0 ;newlen = 0
|
||||
bl L_sysctlbyname$stub ;call sysctlbyname
|
||||
lwz r2,232(r1) ;fetch result
|
||||
addis r8,0,0x8000 ;set initialised bit
|
||||
cmpdi cr5,r3,0 ;assume error means not present
|
||||
cmpwi cr6,r2,0 ;test result
|
||||
blt- cr5,L_co_switch$store_environ
|
||||
beq cr6,L_co_switch$store_environ
|
||||
oris r8,r8,0x4000 ;set the flag to say we have it!
|
||||
L_co_switch$store_environ:
|
||||
stw r8,lo16(_co_environ-L_co_switch$spb)(r29) ;store environment flags
|
||||
L_co_switch$initialised:
|
||||
|
||||
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
|
||||
beq L_co_switch$save_no_vmx
|
||||
mfspr r11,256 ;save VRSAVE
|
||||
andi. r0,r11,0x0FFF ;short-circuit if it's zero
|
||||
stw r11,240(r1)
|
||||
beq L_co_switch$save_no_vmx
|
||||
andi. r0,r11,0x0800 ;check bit 20
|
||||
addi r2,0,48 ;starting index
|
||||
beq L_co_switch$save_skip_vr20
|
||||
stvx v20,r1,r2 ;save VR20
|
||||
L_co_switch$save_skip_vr20:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0400 ;check bit 21
|
||||
beq L_co_switch$save_skip_vr21
|
||||
stvx v21,r1,r2 ;save VR21
|
||||
L_co_switch$save_skip_vr21:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0200 ;check bit 22
|
||||
beq L_co_switch$save_skip_vr22
|
||||
stvx v22,r1,r2 ;save VR22
|
||||
L_co_switch$save_skip_vr22:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0100 ;check bit 23
|
||||
beq L_co_switch$save_skip_vr23
|
||||
stvx v23,r1,r2 ;save VR23
|
||||
L_co_switch$save_skip_vr23:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0080 ;check bit 24
|
||||
beq L_co_switch$save_skip_vr24
|
||||
stvx v24,r1,r2 ;save VR24
|
||||
L_co_switch$save_skip_vr24:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0040 ;check bit 25
|
||||
beq L_co_switch$save_skip_vr25
|
||||
stvx v25,r1,r2 ;save VR25
|
||||
L_co_switch$save_skip_vr25:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0020 ;check bit 26
|
||||
beq L_co_switch$save_skip_vr26
|
||||
stvx v26,r1,r2 ;save VR26
|
||||
L_co_switch$save_skip_vr26:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0010 ;check bit 27
|
||||
beq L_co_switch$save_skip_vr27
|
||||
stvx v27,r1,r2 ;save VR27
|
||||
L_co_switch$save_skip_vr27:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0008 ;check bit 28
|
||||
beq L_co_switch$save_skip_vr28
|
||||
stvx v28,r1,r2 ;save VR28
|
||||
L_co_switch$save_skip_vr28:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0004 ;check bit 29
|
||||
beq L_co_switch$save_skip_vr29
|
||||
stvx v29,r1,r2 ;save VR29
|
||||
L_co_switch$save_skip_vr29:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0002 ;check bit 30
|
||||
beq L_co_switch$save_skip_vr30
|
||||
stvx v30,r1,r2 ;save VR30
|
||||
L_co_switch$save_skip_vr30:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0001 ;check bit 31
|
||||
beq L_co_switch$save_skip_vr31
|
||||
stvx v31,r1,r2 ;save VR31
|
||||
L_co_switch$save_skip_vr31:
|
||||
L_co_switch$save_no_vmx:
|
||||
|
||||
addis r4,r31,ha16(_co_active_context-L_co_switch$spb) ;save current context
|
||||
ld r5,lo16(_co_active_context-L_co_switch$spb)(r4)
|
||||
std r30,lo16(_co_active_context-L_co_switch$spb)(r4);set new context
|
||||
std r1,0(r5) ;save current stack pointer
|
||||
ld r1,0(r30) ;get new stack pointer
|
||||
lwz r12,8(r30) ;have we already set GPR13 (system TLS)?
|
||||
andis. r0,r12,0x8000
|
||||
beq+ L_co_switch$gpr13_set
|
||||
std r13,392(r1)
|
||||
xoris r12,r12,0x8000
|
||||
stw r12,8(r30)
|
||||
L_co_switch$gpr13_set:
|
||||
|
||||
andis. r10,r8,0x4000 ;do we have Altivec/VMX?
|
||||
beq L_co_switch$restore_no_vmx
|
||||
lwz r11,240(r1) ;restore VRSAVE
|
||||
andi. r0,r11,0x0FFF ;short-circuit if it's zero
|
||||
mtspr 256,r11
|
||||
beq L_co_switch$restore_no_vmx
|
||||
andi. r0,r11,0x0800 ;check bit 20
|
||||
addi r2,0,48 ;starting index
|
||||
beq L_co_switch$restore_skip_vr20
|
||||
lvx v20,r1,r2 ;restore VR20
|
||||
L_co_switch$restore_skip_vr20:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0400 ;check bit 21
|
||||
beq L_co_switch$restore_skip_vr21
|
||||
lvx v21,r1,r2 ;restore VR21
|
||||
L_co_switch$restore_skip_vr21:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0200 ;check bit 22
|
||||
beq L_co_switch$restore_skip_vr22
|
||||
lvx v22,r1,r2 ;restore VR22
|
||||
L_co_switch$restore_skip_vr22:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0100 ;check bit 23
|
||||
beq L_co_switch$restore_skip_vr23
|
||||
lvx v23,r1,r2 ;restore VR23
|
||||
L_co_switch$restore_skip_vr23:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0080 ;check bit 24
|
||||
beq L_co_switch$restore_skip_vr24
|
||||
lvx v24,r1,r2 ;restore VR24
|
||||
L_co_switch$restore_skip_vr24:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0040 ;check bit 25
|
||||
beq L_co_switch$restore_skip_vr25
|
||||
lvx v25,r1,r2 ;restore VR25
|
||||
L_co_switch$restore_skip_vr25:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0020 ;check bit 26
|
||||
beq L_co_switch$restore_skip_vr26
|
||||
lvx v26,r1,r2 ;restore VR26
|
||||
L_co_switch$restore_skip_vr26:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0010 ;check bit 27
|
||||
beq L_co_switch$restore_skip_vr27
|
||||
lvx v27,r1,r2 ;restore VR27
|
||||
L_co_switch$restore_skip_vr27:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0008 ;check bit 28
|
||||
beq L_co_switch$restore_skip_vr28
|
||||
lvx v28,r1,r2 ;restore VR28
|
||||
L_co_switch$restore_skip_vr28:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0004 ;check bit 29
|
||||
beq L_co_switch$restore_skip_vr29
|
||||
lvx v29,r1,r2 ;restore VR29
|
||||
L_co_switch$restore_skip_vr29:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0002 ;check bit 30
|
||||
beq L_co_switch$restore_skip_vr30
|
||||
lvx v30,r1,r2 ;restore VR30
|
||||
L_co_switch$restore_skip_vr30:
|
||||
addi r2,r2,16 ;stride
|
||||
andi. r0,r11,0x0001 ;check bit 31
|
||||
beq L_co_switch$restore_skip_vr31
|
||||
lvx v31,r1,r2 ;restore VR31
|
||||
L_co_switch$restore_skip_vr31:
|
||||
L_co_switch$restore_no_vmx:
|
||||
|
||||
lfd f14,248(r1) ;restore preserved FPRs
|
||||
lfd f15,256(r1)
|
||||
lfd f16,264(r1)
|
||||
lfd f17,272(r1)
|
||||
lfd f18,280(r1)
|
||||
lfd f19,288(r1)
|
||||
lfd f20,296(r1)
|
||||
lfd f21,304(r1)
|
||||
lfd f22,312(r1)
|
||||
lfd f23,320(r1)
|
||||
lfd f24,328(r1)
|
||||
lfd f25,336(r1)
|
||||
lfd f26,344(r1)
|
||||
lfd f27,352(r1)
|
||||
lfd f28,360(r1)
|
||||
lfd f29,368(r1)
|
||||
lfd f30,376(r1)
|
||||
lfd f31,384(r1)
|
||||
addi r0,0,0 ;make thread main crash if it returns
|
||||
ld r1,0(r1) ;deallocate stack frame
|
||||
ld r6,16(r1) ;return address in GPR6
|
||||
lwz r7,8(r1) ;condition codes in GPR7
|
||||
ld r13,-152(r1) ;restore preserved GPRs
|
||||
ld r14,-144(r1)
|
||||
ld r15,-136(r1)
|
||||
ld r16,-128(r1)
|
||||
ld r17,-120(r1)
|
||||
ld r18,-112(r1)
|
||||
ld r19,-104(r1)
|
||||
ld r20,-96(r1)
|
||||
ld r21,-88(r1)
|
||||
ld r22,-80(r1)
|
||||
ld r23,-72(r1)
|
||||
ld r24,-64(r1)
|
||||
ld r25,-56(r1)
|
||||
ld r26,-48(r1)
|
||||
ld r27,-40(r1)
|
||||
ld r28,-32(r1)
|
||||
ld r29,-24(r1)
|
||||
ld r30,-16(r1)
|
||||
ld r31,-8(r1)
|
||||
mtlr r0
|
||||
mtctr r6 ;restore return address
|
||||
mtcrf 32,r7 ;restore preserved condition codes
|
||||
mtcrf 16,r7
|
||||
mtcrf 8,r7
|
||||
bctr ;return
|
||||
|
||||
|
||||
|
||||
;Import external functions
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align 5
|
||||
L_malloc$stub:
|
||||
.indirect_symbol _malloc
|
||||
mflr r0
|
||||
bcl 20,31,L_malloc$spb
|
||||
L_malloc$spb:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_malloc$lazy_ptr-L_malloc$spb)
|
||||
mtlr r0
|
||||
ldu r12,lo16(L_malloc$lazy_ptr-L_malloc$spb)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_malloc$lazy_ptr:
|
||||
.indirect_symbol _malloc
|
||||
.quad dyld_stub_binding_helper
|
||||
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align 5
|
||||
L_free$stub:
|
||||
.indirect_symbol _free
|
||||
mflr r0
|
||||
bcl 20,31,L_free$spb
|
||||
L_free$spb:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_free$lazy_ptr-L_free$spb)
|
||||
mtlr r0
|
||||
ldu r12,lo16(L_free$lazy_ptr-L_free$spb)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_free$lazy_ptr:
|
||||
.indirect_symbol _free
|
||||
.quad dyld_stub_binding_helper
|
||||
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align 5
|
||||
L_sysctlbyname$stub:
|
||||
.indirect_symbol _sysctlbyname
|
||||
mflr r0
|
||||
bcl 20,31,L_sysctlbyname$spb
|
||||
L_sysctlbyname$spb:
|
||||
mflr r11
|
||||
addis r11,r11,ha16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)
|
||||
mtlr r0
|
||||
ldu r12,lo16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.lazy_symbol_pointer
|
||||
L_sysctlbyname$lazy_ptr:
|
||||
.indirect_symbol _sysctlbyname
|
||||
.quad dyld_stub_binding_helper
|
||||
|
||||
|
||||
;This needs to be here!
|
||||
|
||||
.subsections_via_symbols
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
libco.ucontext (2007-09-08)
|
||||
author: byuu
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ucontext.h>
|
||||
#include "../libco.h"
|
||||
|
||||
//WARNING: the overhead of POSIX ucontext is very high,
|
||||
//averaging ~450x that of standard subroutine calls.
|
||||
//(tested on FreeBSD 6.2-RELEASE)
|
||||
//By contrast, on the same system, libco_x86's overhead
|
||||
//is ~7.25x standard subroutine calls; or fifty times faster.
|
||||
//
|
||||
//This library only exists for two reasons:
|
||||
//1 - as an initial test for the viability of a ucontext implementation
|
||||
//2 - to demonstrate the power and speed of libco over existing implementations,
|
||||
// such as pth (which defaults to wrapping ucontext on unix targets)
|
||||
//
|
||||
//Use this library only as a *last resort*
|
||||
|
||||
struct cothread_struct {
|
||||
ucontext_t cohandle;
|
||||
void (*coentry)();
|
||||
};
|
||||
|
||||
cothread_t __co_active = 0, __co_primary = 0;
|
||||
void co_entrypoint(cothread_t cothread);
|
||||
void co_init();
|
||||
|
||||
/*****
|
||||
* library functions
|
||||
*****/
|
||||
|
||||
cothread_t co_active() {
|
||||
if(__co_primary == 0)co_init();
|
||||
return __co_active;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int heapsize, void (*coentry)()) {
|
||||
if(__co_primary == 0)co_init();
|
||||
cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct));
|
||||
thread->coentry = coentry;
|
||||
getcontext(&thread->cohandle);
|
||||
heapsize += 512;
|
||||
thread->cohandle.uc_stack.ss_sp = (char*)malloc(heapsize);
|
||||
thread->cohandle.uc_stack.ss_size = heapsize;
|
||||
makecontext(&thread->cohandle, (void (*)())co_entrypoint, 1, thread);
|
||||
return (cothread_t)thread;
|
||||
}
|
||||
|
||||
void co_delete(cothread_t cothread) {
|
||||
cothread_struct *thread = (cothread_struct*)cothread;
|
||||
free(thread->cohandle.uc_stack.ss_sp);
|
||||
free(thread);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t cothread) {
|
||||
cothread_struct *active = (cothread_struct*)__co_active;
|
||||
cothread_struct *swap = (cothread_struct*)cothread;
|
||||
__co_active = cothread;
|
||||
swapcontext(&active->cohandle, &swap->cohandle);
|
||||
}
|
||||
|
||||
/*****
|
||||
* internal functions
|
||||
*****/
|
||||
|
||||
void co_entrypoint(cothread_t cothread) {
|
||||
((cothread_struct*)cothread)->coentry();
|
||||
}
|
||||
|
||||
void co_init() {
|
||||
cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct));
|
||||
thread->coentry = 0;
|
||||
getcontext(&thread->cohandle);
|
||||
__co_active = __co_primary = (cothread_t)thread;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
libco.win (2007-09-08)
|
||||
author: byuu
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#define WINVER 0x0400
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#include <windows.h>
|
||||
#include "../libco.h"
|
||||
|
||||
struct cothread_struct {
|
||||
void *cohandle;
|
||||
void (*coentry)();
|
||||
};
|
||||
|
||||
cothread_t __co_active = 0, __co_primary = 0;
|
||||
|
||||
void __stdcall co_entryproc(void*);
|
||||
cothread_t co_init();
|
||||
|
||||
/*****
|
||||
* library functions
|
||||
*****/
|
||||
|
||||
cothread_t co_active() {
|
||||
if(__co_primary == 0)co_init();
|
||||
return __co_active;
|
||||
}
|
||||
|
||||
cothread_t co_create(unsigned int heapsize, void (*coentry)()) {
|
||||
if(__co_primary == 0)co_init();
|
||||
cothread_struct *s = (cothread_struct*)malloc(sizeof(cothread_struct));
|
||||
s->coentry = coentry;
|
||||
s->cohandle = CreateFiber(heapsize + 512, co_entryproc, (void*)s);
|
||||
return (cothread_t)s;
|
||||
}
|
||||
|
||||
void co_delete(cothread_t cothread) {
|
||||
cothread_struct *s = (cothread_struct*)cothread;
|
||||
DeleteFiber(s->cohandle);
|
||||
free(cothread);
|
||||
}
|
||||
|
||||
void co_switch(cothread_t cothread) {
|
||||
__co_active = cothread;
|
||||
cothread_struct *s = (cothread_struct*)cothread;
|
||||
SwitchToFiber(s->cohandle);
|
||||
}
|
||||
|
||||
/*****
|
||||
* internal functions
|
||||
*****/
|
||||
|
||||
void __stdcall co_entryproc(void *cothread) {
|
||||
((cothread_struct*)cothread)->coentry();
|
||||
}
|
||||
|
||||
cothread_t co_init() {
|
||||
ConvertThreadToFiber(0);
|
||||
cothread_struct *s = (cothread_struct*)malloc(sizeof(cothread_struct));
|
||||
s->coentry = 0;
|
||||
s->cohandle = GetCurrentFiber();
|
||||
__co_active = __co_primary = (cothread_t)s;
|
||||
return __co_active;
|
||||
}
|
||||
@@ -1,123 +1,146 @@
|
||||
;*****
|
||||
;libco_x86_64 : version 0.10 ~byuu (2007-09-08)
|
||||
;cross-platform x86-64 implementation of libco
|
||||
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf )
|
||||
;- gcc; linux; x86-64
|
||||
;- gcc; freebsd; x86-64
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- rsp, rbp, rbx, r12, r13, r14, r15
|
||||
;
|
||||
;[volatile registers]
|
||||
;- rax, rcx, rdx, r8, r9, r10, r11, rdi, rsi
|
||||
;- st0 - st7
|
||||
;- xmm0 - xmm15
|
||||
;*****
|
||||
|
||||
bits 64
|
||||
|
||||
section .bss
|
||||
|
||||
align 8
|
||||
co_primary_buffer resb 512
|
||||
|
||||
section .data
|
||||
|
||||
align 8
|
||||
co_active_context dq co_primary_buffer
|
||||
|
||||
section .text
|
||||
|
||||
extern malloc
|
||||
extern free
|
||||
|
||||
global co_active
|
||||
global co_create
|
||||
global co_delete
|
||||
global co_switch
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_active();
|
||||
;return = rax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_active:
|
||||
mov rax,[co_active_context wrt rip]
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
;rdi = heapsize
|
||||
;rsi = coentry
|
||||
;return = rax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_create:
|
||||
;create heap space (stack + register storage)
|
||||
add rdi,512 ;allocate extra memory for contextual info
|
||||
push rdi
|
||||
push rsi
|
||||
|
||||
call malloc ;rax = malloc(rdi)
|
||||
|
||||
pop rsi
|
||||
pop rdi
|
||||
|
||||
add rdi,rax ;set rsi to point to top of stack heap
|
||||
and rdi,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov qword[rdi-8],rsi ;entry point
|
||||
mov qword[rdi-16],0 ;r15
|
||||
mov qword[rdi-24],0 ;r14
|
||||
mov qword[rdi-32],0 ;r13
|
||||
mov qword[rdi-40],0 ;r12
|
||||
mov qword[rdi-48],0 ;rbx
|
||||
mov qword[rdi-56],0 ;rbp
|
||||
sub rdi,56
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [rax],rdi ;*cothread_t = stack heap pointer (rsp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
;extern "C" void co_delete(cothread_t cothread);
|
||||
;rdi = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_delete:
|
||||
jmp free ;free(rdi)
|
||||
|
||||
;*****
|
||||
;extern "C" void co_switch(cothread_t cothread);
|
||||
;rdi = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_switch:
|
||||
mov rax,[co_active_context wrt rip] ;backup current context
|
||||
mov [co_active_context wrt rip],rdi ;set new active context
|
||||
|
||||
push rbp
|
||||
push rbx
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
mov [rax],rsp
|
||||
|
||||
mov rsp,[rdi]
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbx
|
||||
pop rbp
|
||||
|
||||
ret
|
||||
;*****
|
||||
;libco.x86-64 (2007-12-11)
|
||||
;author: byuu
|
||||
;license: public domain
|
||||
;
|
||||
;cross-platform x86-64 implementation of libco
|
||||
;thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;thanks to Lucas Newman and Vas Crabb for assistance with OS X support
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf )
|
||||
;- gcc; mac os x; x86-64
|
||||
;- gcc; linux; x86-64
|
||||
;- gcc; freebsd; x86-64
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- rsp, rbp, rbx, r12, r13, r14, r15
|
||||
;
|
||||
;[volatile registers]
|
||||
;- rax, rcx, rdx, r8, r9, r10, r11, rdi, rsi
|
||||
;- st0 - st7
|
||||
;- xmm0 - xmm15
|
||||
;*****
|
||||
|
||||
;*****
|
||||
;linker-specific name decorations
|
||||
;*****
|
||||
|
||||
%ifdef OSX
|
||||
%define malloc _malloc
|
||||
%define free _free
|
||||
|
||||
%define co_active _co_active
|
||||
%define co_create _co_create
|
||||
%define co_delete _co_delete
|
||||
%define co_switch _co_switch
|
||||
%endif
|
||||
|
||||
bits 64
|
||||
|
||||
section .bss
|
||||
|
||||
align 8
|
||||
co_primary_buffer resb 512
|
||||
|
||||
section .data
|
||||
|
||||
align 8
|
||||
co_active_context dq co_primary_buffer
|
||||
|
||||
section .text
|
||||
|
||||
extern malloc
|
||||
extern free
|
||||
|
||||
global co_active
|
||||
global co_create
|
||||
global co_delete
|
||||
global co_switch
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_active();
|
||||
;return = rax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_active:
|
||||
mov rax,[co_active_context wrt rip]
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
;rdi = heapsize
|
||||
;rsi = coentry
|
||||
;return = rax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_create:
|
||||
;create heap space (stack + context)
|
||||
add rdi,512 ;allocate extra memory for contextual info
|
||||
|
||||
push rdi ;backup volatile registers before malloc call
|
||||
push rsi
|
||||
|
||||
sub rsp,8 ;SSE 16-byte stack alignment
|
||||
call malloc ;rax = malloc(rdi)
|
||||
add rsp,8
|
||||
|
||||
pop rsi ;restore volatile registers
|
||||
pop rdi
|
||||
|
||||
add rdi,rax ;set rdi to point to top of stack heap
|
||||
and rdi,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov qword[rdi-8],0 ;crash if entry point returns
|
||||
mov qword[rdi-16],rsi ;entry point
|
||||
mov qword[rdi-24],0 ;r15
|
||||
mov qword[rdi-32],0 ;r14
|
||||
mov qword[rdi-40],0 ;r13
|
||||
mov qword[rdi-48],0 ;r12
|
||||
mov qword[rdi-56],0 ;rbx
|
||||
mov qword[rdi-64],0 ;rbp
|
||||
sub rdi,64
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [rax],rdi ;*cothread_t = stack heap pointer (rsp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
;extern "C" void co_delete(cothread_t cothread);
|
||||
;rdi = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_delete:
|
||||
jmp free ;free(rdi)
|
||||
|
||||
;*****
|
||||
;extern "C" void co_switch(cothread_t cothread);
|
||||
;rdi = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_switch:
|
||||
mov rax,[co_active_context wrt rip] ;backup current context
|
||||
mov [co_active_context wrt rip],rdi ;set new active context
|
||||
|
||||
push rbp
|
||||
push rbx
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
mov [rax],rsp
|
||||
|
||||
mov rsp,[rdi]
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbx
|
||||
pop rbp
|
||||
|
||||
ret
|
||||
@@ -1,148 +1,155 @@
|
||||
;*****
|
||||
;libco_x86 : version 0.10 ~byuu (2007-09-08)
|
||||
;cross-platform x86 implementation of libco
|
||||
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- visual c++; windows; x86
|
||||
;- mingw; windows; x86
|
||||
;- gcc; mac os x; x86
|
||||
;- gcc; linux; x86
|
||||
;- gcc; freebsd; x86
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- esp, ebp, edi, esi, ebx
|
||||
;
|
||||
;[volatile registers]
|
||||
;- eax, ecx, edx
|
||||
;- st0 - st7
|
||||
;- xmm0 - xmm15
|
||||
;*****
|
||||
|
||||
;*****
|
||||
;linker-specific name decorations
|
||||
;*****
|
||||
|
||||
%ifdef WIN32
|
||||
%define malloc _malloc
|
||||
%define free _free
|
||||
|
||||
%define co_active @co_active@0
|
||||
%define co_create @co_create@8
|
||||
%define co_delete @co_delete@4
|
||||
%define co_switch @co_switch@4
|
||||
%endif
|
||||
|
||||
%ifdef OSX86
|
||||
%define malloc _malloc
|
||||
%define free _free
|
||||
|
||||
%define co_active _co_active
|
||||
%define co_create _co_create
|
||||
%define co_delete _co_delete
|
||||
%define co_switch _co_switch
|
||||
%endif
|
||||
|
||||
bits 32
|
||||
|
||||
section .bss
|
||||
|
||||
align 4
|
||||
co_primary_buffer resb 512
|
||||
|
||||
section .data
|
||||
|
||||
align 4
|
||||
co_active_context dd co_primary_buffer
|
||||
|
||||
section .text
|
||||
|
||||
extern malloc
|
||||
extern free
|
||||
|
||||
global co_active
|
||||
global co_create
|
||||
global co_delete
|
||||
global co_switch
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t fastcall co_active();
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_active:
|
||||
mov eax,[co_active_context]
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
|
||||
;ecx = heapsize
|
||||
;edx = coentry
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_create:
|
||||
;create heap space (stack + register storage)
|
||||
add ecx,512 ;allocate extra memory for contextual info
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
push ecx
|
||||
call malloc ;eax = malloc(edx)
|
||||
add esp,4
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
|
||||
add ecx,eax ;set edx to point to top of stack heap
|
||||
and ecx,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov dword[ecx-4],edx ;entry point
|
||||
mov dword[ecx-8],0 ;ebp
|
||||
mov dword[ecx-12],0 ;esi
|
||||
mov dword[ecx-16],0 ;edi
|
||||
mov dword[ecx-20],0 ;ebx
|
||||
sub ecx,20
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [eax],ecx ;*cothread_t = stack heap pointer (esp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
;ecx = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_delete:
|
||||
push ecx
|
||||
call free ;free(ecx)
|
||||
add esp,4
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_switch(cothread_t cothread);
|
||||
;ecx = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_switch:
|
||||
mov eax,[co_active_context] ;backup current context
|
||||
mov [co_active_context],ecx ;set new active context
|
||||
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov [eax],esp
|
||||
|
||||
mov esp,[ecx]
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
|
||||
ret
|
||||
;*****
|
||||
;libco.x86 (2007-12-11)
|
||||
;author: byuu
|
||||
;license: public domain
|
||||
;
|
||||
;cross-platform x86 implementation of libco
|
||||
;thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;thanks to Lucas Newman and Vas Crabb for assistance with OS X support
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- visual c++; windows; x86
|
||||
;- mingw; windows; x86
|
||||
;- gcc; mac os x; x86
|
||||
;- gcc; linux; x86
|
||||
;- gcc; freebsd; x86
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- esp, ebp, edi, esi, ebx
|
||||
;
|
||||
;[volatile registers]
|
||||
;- eax, ecx, edx
|
||||
;- st0 - st7
|
||||
;- xmm0 - xmm15
|
||||
;*****
|
||||
|
||||
;*****
|
||||
;linker-specific name decorations
|
||||
;*****
|
||||
|
||||
%ifdef WIN
|
||||
%define malloc _malloc
|
||||
%define free _free
|
||||
|
||||
%define co_active @co_active@0
|
||||
%define co_create @co_create@8
|
||||
%define co_delete @co_delete@4
|
||||
%define co_switch @co_switch@4
|
||||
%endif
|
||||
|
||||
%ifdef OSX
|
||||
%define malloc _malloc
|
||||
%define free _free
|
||||
|
||||
%define co_active _co_active
|
||||
%define co_create _co_create
|
||||
%define co_delete _co_delete
|
||||
%define co_switch _co_switch
|
||||
%endif
|
||||
|
||||
bits 32
|
||||
|
||||
section .bss
|
||||
|
||||
align 4
|
||||
co_primary_buffer resb 512
|
||||
|
||||
section .data
|
||||
|
||||
align 4
|
||||
co_active_context dd co_primary_buffer
|
||||
|
||||
section .text
|
||||
|
||||
extern malloc
|
||||
extern free
|
||||
|
||||
global co_active
|
||||
global co_create
|
||||
global co_delete
|
||||
global co_switch
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t fastcall co_active();
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_active:
|
||||
mov eax,[co_active_context]
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
|
||||
;ecx = heapsize
|
||||
;edx = coentry
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_create:
|
||||
;create heap space (stack + context)
|
||||
add ecx,512 ;allocate extra memory for contextual info
|
||||
|
||||
push ecx ;backup volatile registers before malloc call
|
||||
push edx
|
||||
|
||||
push ecx
|
||||
call malloc ;eax = malloc(ecx)
|
||||
add esp,4
|
||||
|
||||
pop edx ;restore volatile registers
|
||||
pop ecx
|
||||
|
||||
add ecx,eax ;set edx to point to top of stack heap
|
||||
and ecx,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov dword[ecx-4],0 ;crash if entry point returns
|
||||
mov dword[ecx-8],edx ;entry point
|
||||
mov dword[ecx-12],0 ;ebp
|
||||
mov dword[ecx-16],0 ;esi
|
||||
mov dword[ecx-20],0 ;edi
|
||||
mov dword[ecx-24],0 ;ebx
|
||||
sub ecx,24
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [eax],ecx ;*cothread_t = stack heap pointer (esp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
;ecx = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_delete:
|
||||
sub esp,8 ;SSE 16-byte stack alignment
|
||||
push ecx
|
||||
call free ;free(ecx)
|
||||
add esp,4+8
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_switch(cothread_t cothread);
|
||||
;ecx = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_switch:
|
||||
mov eax,[co_active_context] ;backup current context
|
||||
mov [co_active_context],ecx ;set new active context
|
||||
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov [eax],esp
|
||||
|
||||
mov esp,[ecx]
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
|
||||
ret
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
libco_x86 : version 0.10 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
#if !defined(fastcall)
|
||||
#if defined(_MSC_VER)
|
||||
#define fastcall __fastcall
|
||||
#elif defined(__GNUC__)
|
||||
#define fastcall __attribute__((fastcall))
|
||||
#else
|
||||
#error "fastcall undefined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef void *cothread_t;
|
||||
|
||||
extern "C" cothread_t fastcall co_active();
|
||||
extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
|
||||
extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
extern "C" void fastcall co_switch(cothread_t cothread);
|
||||
|
||||
#endif
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
libco_x86_64 : version 0.10 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
typedef void *cothread_t;
|
||||
|
||||
extern "C" cothread_t co_active();
|
||||
extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
extern "C" void co_delete(cothread_t cothread);
|
||||
extern "C" void co_switch(cothread_t cothread);
|
||||
|
||||
#endif
|
||||
@@ -1,456 +0,0 @@
|
||||
#include "libbase.h"
|
||||
#include "libstring.h"
|
||||
#include "libstring_oo.cpp"
|
||||
|
||||
#include "libstring_array.cpp"
|
||||
|
||||
char chrlower(char c) {
|
||||
if(c >= 'A' && c <= 'Z')return c + ('a' - 'A');
|
||||
return c;
|
||||
}
|
||||
|
||||
char chrupper(char c) {
|
||||
if(c >= 'a' && c <= 'z')return c - ('a' - 'A');
|
||||
return c;
|
||||
}
|
||||
|
||||
char *strptr(const string &str) { return str.s; }
|
||||
uint strlen(const string &str) { return strlen(strptr(str)); }
|
||||
|
||||
int strcmp(const string &dest, const char *src) { return strcmp(strptr(dest), src); }
|
||||
int strcmp(const char *dest, const string &src) { return strcmp(dest, strptr(src)); }
|
||||
int strcmp(const string &dest, const string &src) { return strcmp(strptr(dest), strptr(src)); }
|
||||
|
||||
int __stricmp(const char *dest, const char *src) {
|
||||
while(*dest) {
|
||||
if(chrlower(*dest) != chrlower(*src))break;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
return (int)chrlower(*dest) - (int)chrlower(*src);
|
||||
}
|
||||
int stricmp(const string &dest, const char *src) { return __stricmp(strptr(dest), src); }
|
||||
int stricmp(const char *dest, const string &src) { return __stricmp(dest, strptr(src)); }
|
||||
int stricmp(const string &dest, const string &src) { return __stricmp(strptr(dest), strptr(src)); }
|
||||
|
||||
void strcpy(string &dest, const char *src) {
|
||||
int srclen = strlen(src);
|
||||
dest.reserve(srclen);
|
||||
strcpy(dest.s, src);
|
||||
}
|
||||
void strcpy(string &dest, const string &src) { strcpy(dest, strptr(src)); }
|
||||
|
||||
uint strlcpy(char *dest, const char *src, uint length) {
|
||||
uint srclen = strlen(src);
|
||||
length--;
|
||||
if(length > srclen)length = srclen;
|
||||
memcpy(dest, src, length);
|
||||
dest[length] = 0;
|
||||
return srclen;
|
||||
}
|
||||
|
||||
uint strlcpy(string &dest, const char *src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcpy(strptr(dest), src, length);
|
||||
}
|
||||
|
||||
uint strlcpy(string &dest, const string &src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcpy(strptr(dest), strptr(src), length);
|
||||
}
|
||||
|
||||
void strcat(string &dest, const char *src) {
|
||||
int srclen = strlen(src);
|
||||
int destlen = strlen(dest);
|
||||
dest.reserve(srclen + destlen);
|
||||
strcat(dest.s, src);
|
||||
}
|
||||
void strcat(string &dest, const string &src) { strcat(dest, strptr(src)); }
|
||||
|
||||
uint strlcat(char *dest, const char *src, uint length) {
|
||||
uint destlen = strlen(dest), srclen = strlen(src);
|
||||
length--;
|
||||
if(length > destlen + srclen)length = destlen + srclen;
|
||||
memcpy(dest + destlen, src, length - destlen);
|
||||
dest[length] = 0;
|
||||
return destlen + srclen;
|
||||
}
|
||||
|
||||
uint strlcat(string &dest, const char *src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcat(strptr(dest), src, length);
|
||||
}
|
||||
|
||||
uint strlcat(string &dest, const string &src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcat(strptr(dest), strptr(src), length);
|
||||
}
|
||||
|
||||
string substr(string &dest, const char *src, uint start, uint length) {
|
||||
string temp;
|
||||
if(length == 0) {
|
||||
//copy entire string
|
||||
strcpy(temp, src + start);
|
||||
} else {
|
||||
//copy partial string
|
||||
strlcpy(temp, src + start, length + 1);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
string substr(string &dest, const string &src, uint start, uint length) { return substr(dest, strptr(src), start, length); }
|
||||
|
||||
void strinsert(string &dest, const char *src, uint pos) {
|
||||
string temp;
|
||||
strcpy(temp, strptr(dest) + pos);
|
||||
dest[pos] = 0;
|
||||
strcat(dest, src);
|
||||
strcat(dest, temp);
|
||||
}
|
||||
void strinsert(string &dest, const string &src, uint pos) { strinsert(dest, strptr(src), pos); }
|
||||
|
||||
void strremove(string &dest, uint start, uint length) {
|
||||
int i, destlen = strlen(dest);
|
||||
dest.reserve(start);
|
||||
if(!length) {
|
||||
dest[start] = 0;
|
||||
return;
|
||||
}
|
||||
for(i = start; i < destlen; i++) { dest.s[i] = dest.s[i + length]; }
|
||||
dest.s[i] = 0;
|
||||
}
|
||||
|
||||
char *strlower(char *str) {
|
||||
uint i = 0;
|
||||
while(str[i]) {
|
||||
str[i] = chrlower(str[i]);
|
||||
i++;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
string &strlower(string &str) { strlower(strptr(str)); return str; }
|
||||
|
||||
char *strupper(char *str) {
|
||||
uint i = 0;
|
||||
while(str[i]) {
|
||||
str[i] = chrupper(str[i]);
|
||||
i++;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
string &strupper(string &str) { strupper(strptr(str)); return str; }
|
||||
|
||||
int strpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return -1;
|
||||
for(int i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int strpos(const string &str, const char *key) { return strpos(strptr(str), key); }
|
||||
int strpos(const char *str, const string &key) { return strpos(str, strptr(key)); }
|
||||
int strpos(const string &str, const string &key) { return strpos(strptr(str), strptr(key)); }
|
||||
|
||||
int qstrpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return -1;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
uint8 x = str[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
uint8 z = i++;
|
||||
while(str[i] != x && i < ssl)i++;
|
||||
if(i >= ssl)i = z;
|
||||
}
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int qstrpos(const string &str, const char *key) { return qstrpos(strptr(str), key); }
|
||||
int qstrpos(const char *str, const string &key) { return qstrpos(str, strptr(key)); }
|
||||
int qstrpos(const string &str, const string &key) { return qstrpos(strptr(str), strptr(key)); }
|
||||
|
||||
void strtr(char *dest, const char *before, const char *after) {
|
||||
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
|
||||
if(bsl != asl || bsl == 0)return;
|
||||
for(int i = 0; i < sl; i++) {
|
||||
for(int l = 0; l < bsl; l++) {
|
||||
if(dest[i] == before[l]) {
|
||||
dest[i] = after[l];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void strtr(string &dest, const char *before, const char *after) { strtr(strptr(dest), before, after); }
|
||||
|
||||
bool strbegin(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
return (!memcmp(str, key, ksl));
|
||||
}
|
||||
bool strbegin(const string &str, const char *key) { return strbegin(strptr(str), key); }
|
||||
|
||||
bool stribegin(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
for(int i = 0; i < ksl; i++) {
|
||||
if(str[i] >= 'A' && str[i] <= 'Z') {
|
||||
if(str[i] != key[i] && str[i]+0x20 != key[i])return false;
|
||||
} else if(str[i] >= 'a' && str[i] <= 'z') {
|
||||
if(str[i] != key[i] && str[i]-0x20 != key[i])return false;
|
||||
} else {
|
||||
if(str[i] != key[i])return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool stribegin(const string &str, const char *key) { return stribegin(strptr(str), key); }
|
||||
|
||||
bool strend(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
return (!memcmp(str + ssl - ksl, key, ksl));
|
||||
}
|
||||
bool strend(const string &str, const char *key) { return strend(strptr(str), key); }
|
||||
|
||||
bool striend(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return false;
|
||||
for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) {
|
||||
if(str[i] >= 'A' && str[i] <= 'Z') {
|
||||
if(str[i] != key[z] && str[i]+0x20 != key[z])return false;
|
||||
} else if(str[i] >= 'a' && str[i] <= 'z') {
|
||||
if(str[i] != key[z] && str[i]-0x20 != key[z])return false;
|
||||
} else {
|
||||
if(str[i] != key[z])return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool striend(const string &str, const char *key) { return striend(strptr(str), key); }
|
||||
|
||||
void strltrim(char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(strbegin(str, key)) {
|
||||
for(i = 0; i < (ssl - ksl); i++)str[i] = str[i + ksl];
|
||||
str[i] = 0;
|
||||
}
|
||||
}
|
||||
void strltrim(string &str, const char *key) { strltrim(strptr(str), key); }
|
||||
|
||||
void striltrim(char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(stribegin(str, key)) {
|
||||
for(i = 0; i < (ssl-ksl); i++)str[i] = str[i + ksl];
|
||||
str[i] = 0;
|
||||
}
|
||||
}
|
||||
void striltrim(string &str, const char *key) { striltrim(strptr(str), key); }
|
||||
|
||||
void strrtrim(char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(strend(str, key)) {
|
||||
str[ssl - ksl] = 0;
|
||||
}
|
||||
}
|
||||
void strrtrim(string &str, const char *key) { strrtrim(strptr(str), key); }
|
||||
|
||||
void strirtrim(char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl)return;
|
||||
if(striend(str, key)) {
|
||||
str[ssl - ksl] = 0;
|
||||
}
|
||||
}
|
||||
void strirtrim(string &str, const char *key) { strirtrim(strptr(str), key); }
|
||||
|
||||
void strtrim(char *str, const char *key) {
|
||||
strltrim(str, key);
|
||||
strrtrim(str, key);
|
||||
}
|
||||
void strtrim(string &str, const char *key) { strtrim(strptr(str), key); }
|
||||
|
||||
void stritrim(char *str, const char *key) {
|
||||
striltrim(str, key);
|
||||
strirtrim(str, key);
|
||||
}
|
||||
void stritrim(string &str, const char *key) { stritrim(strptr(str), key); }
|
||||
|
||||
//does not support char* type because function increases string length
|
||||
void strquote(string &str) {
|
||||
string t;
|
||||
strcpy(t, "\"");
|
||||
strcat(t, str);
|
||||
strcat(t, "\"");
|
||||
strcpy(str, t);
|
||||
}
|
||||
|
||||
bool strunquote(char *str) {
|
||||
int i, ssl = strlen(str);
|
||||
//make sure string is long enough to have quotes
|
||||
if(ssl < 2)return false;
|
||||
|
||||
//make sure string actually has quotes
|
||||
if(str[0] == '\"' && str[ssl - 1] == '\"');
|
||||
else if(str[0] == '\'' && str[ssl - 1] == '\'');
|
||||
else return false;
|
||||
|
||||
//now remove them
|
||||
for(i = 0; i < ssl; i++) {
|
||||
str[i] = str[i + 1];
|
||||
}
|
||||
str[i - 2] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool strunquote(string &str) { return strunquote(strptr(str)); }
|
||||
|
||||
uint strhex(const char *str) {
|
||||
uint r = 0, m = 0;
|
||||
int i = 0, ssl = strlen(str);
|
||||
uint8 x;
|
||||
bool negate = (str[0] == '-');
|
||||
if(negate)i++;
|
||||
for(; i < ssl; i++) {
|
||||
if(str[i] >= '0' && str[i] <= '9');
|
||||
else if(str[i] >= 'A' && str[i] <= 'F');
|
||||
else if(str[i] >= 'a' && str[i] <= 'f');
|
||||
else break;
|
||||
}
|
||||
for(--i; i >= 0; i--, m += 4) {
|
||||
x = str[i];
|
||||
if(x >= '0' && x <= '9')x -= '0';
|
||||
else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a;
|
||||
else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a;
|
||||
else break;
|
||||
r |= x << m;
|
||||
}
|
||||
return !negate ? r : (uint)-r;
|
||||
}
|
||||
uint strhex(const string &str) { return strhex(strptr(str)); }
|
||||
|
||||
uint strdec(const char *str) {
|
||||
uint m = 1;
|
||||
int i = 0, r = 0, ssl = strlen(str);
|
||||
uint8 x;
|
||||
bool negate = (str[0] == '-');
|
||||
if(negate)i++;
|
||||
for(; i < ssl; i++) {
|
||||
if(str[i] >= '0' && str[i] <= '9');
|
||||
else break;
|
||||
}
|
||||
for(--i; i >= 0; i--, m *= 10) {
|
||||
x = str[i];
|
||||
if(x >= '0' && x <= '9')x -= '0';
|
||||
else break;
|
||||
r += x * m;
|
||||
}
|
||||
return !negate ? r : (uint)-r;
|
||||
}
|
||||
uint strdec(const string &str) { return strdec(strptr(str)); }
|
||||
|
||||
uint strbin(const char *str) {
|
||||
uint r = 0, m = 0;
|
||||
int i = 0, ssl = strlen(str);
|
||||
uint8 x;
|
||||
bool negate = (str[0] == '-');
|
||||
if(negate)i++;
|
||||
for(; i < ssl; i++) {
|
||||
if(str[i] == '0' || str[i] == '1');
|
||||
else break;
|
||||
}
|
||||
for(--i; i >= 0; i--, m++) {
|
||||
x = str[i];
|
||||
if(str[i] == '0' || str[i] == '1')x -= '0';
|
||||
else break;
|
||||
r |= x << m;
|
||||
}
|
||||
return !negate ? r : (uint)-r;
|
||||
}
|
||||
uint strbin(const string &str) { return strbin(strptr(str)); }
|
||||
|
||||
char *utoa(char *str, uint num) {
|
||||
sprintf(str, "%u", num);
|
||||
return str;
|
||||
}
|
||||
|
||||
string &utoa(string &str, uint num) {
|
||||
str.reserve(16);
|
||||
utoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
||||
char *itoa(char *str, uint num) {
|
||||
sprintf(str, "%d", num);
|
||||
return str;
|
||||
}
|
||||
|
||||
string &itoa(string &str, uint num) {
|
||||
str.reserve(16);
|
||||
itoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
||||
char *htoa(char *str, uint num) {
|
||||
sprintf(str, "%x", num);
|
||||
return str;
|
||||
}
|
||||
|
||||
string &htoa(string &str, uint num) {
|
||||
str.reserve(16);
|
||||
htoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
||||
char *btoa(char *str, uint num) {
|
||||
char *pstr = str;
|
||||
uint mask = 0x80000000;
|
||||
while(mask && (num & mask) == 0)mask >>= 1;
|
||||
while(mask > 1) {
|
||||
str[0] = (num & mask) ? '1' : '0';
|
||||
str++;
|
||||
mask >>= 1;
|
||||
}
|
||||
str[0] = (num & mask) ? '1' : '0';
|
||||
str++;
|
||||
str[0] = 0;
|
||||
return pstr;
|
||||
}
|
||||
|
||||
string &btoa(string &str, uint num) {
|
||||
str.reserve(64);
|
||||
btoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
||||
bool strfread(string &str, const char *filename) {
|
||||
strcpy(str, "");
|
||||
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if(!fp)return false;
|
||||
|
||||
uint size = fsize(fp);
|
||||
char *fdata = (char*)malloc(size + 1);
|
||||
fread(fdata, 1, size, fp);
|
||||
fclose(fp);
|
||||
fdata[size] = 0;
|
||||
strcpy(str, fdata);
|
||||
free(fdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "libstring_int.cpp"
|
||||
#include "libstring_math.cpp"
|
||||
#include "libstring_split.cpp"
|
||||
#include "libstring_replace.cpp"
|
||||
#include "libstring_sprintf.cpp"
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
libstring : version 0.18 ~byuu (2007-06-06)
|
||||
*/
|
||||
|
||||
#ifndef LIBSTRING_H
|
||||
#define LIBSTRING_H
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libvector.h"
|
||||
|
||||
class string;
|
||||
typedef linear_vector<string> stringarray;
|
||||
|
||||
char chrlower(char c);
|
||||
char chrupper(char c);
|
||||
|
||||
uint count(stringarray &str);
|
||||
|
||||
int find(stringarray &str, const char *key);
|
||||
int find(stringarray &str, const string &key);
|
||||
|
||||
char *strptr(const string &str);
|
||||
uint strlen(const string &str);
|
||||
|
||||
int strcmp(const string &dest, const char *src);
|
||||
int strcmp(const char *dest, const string &src);
|
||||
int strcmp(const string &dest, const string &src);
|
||||
|
||||
//vc6/win32 and gcc/dos only support stricmp, whereas
|
||||
//gcc/unix only supports strcasecmp. this is an attempt
|
||||
//to avoid platform-specific defines...
|
||||
#define stricmp __stricmp
|
||||
int __stricmp(const char *dest, const char *src);
|
||||
int stricmp(const string &dest, const char *src);
|
||||
int stricmp(const char *dest, const string &src);
|
||||
int stricmp(const string &dest, const string &src);
|
||||
|
||||
void strcpy(string &dest, const char *src);
|
||||
void strcpy(string &dest, const string &src);
|
||||
uint strlcpy(char *dest, const char *src, uint length);
|
||||
uint strlcpy(string &dest, const char *src, uint length);
|
||||
uint strlcpy(string &dest, const string &src, uint length);
|
||||
|
||||
void strcat(string &dest, const char *src);
|
||||
void strcat(string &dest, const string &src);
|
||||
uint strlcat(char *dest, const char *src, uint length);
|
||||
uint strlcat(string &dest, const char *src, uint length);
|
||||
uint strlcat(string &dest, const string &src, uint length);
|
||||
|
||||
string substr(string &dest, const char *src, uint start = 0, uint length = 0);
|
||||
string substr(string &dest, const string &src, uint start = 0, uint length = 0);
|
||||
|
||||
void strinsert(string &dest, const char *src, uint pos);
|
||||
void strinsert(string &dest, const string &src, uint pos);
|
||||
|
||||
void strremove(string &dest, uint start, uint length = 0);
|
||||
|
||||
char *strlower(char *str);
|
||||
string &strlower(string &str);
|
||||
|
||||
char *strupper(char *str);
|
||||
string &strupper(string &str);
|
||||
|
||||
int strpos(const char *str, const char *key);
|
||||
int strpos(const string &str, const char *key);
|
||||
int strpos(const char *str, const string &key);
|
||||
int strpos(const string &str, const string &key);
|
||||
|
||||
int qstrpos(const char *str, const char *key);
|
||||
int qstrpos(const string &str, const char *key);
|
||||
int qstrpos(const char *str, const string &key);
|
||||
int qstrpos(const string &str, const string &key);
|
||||
|
||||
void strtr(char *dest, const char *before, const char *after);
|
||||
void strtr(string &dest, const char *before, const char *after);
|
||||
|
||||
bool strbegin(const char *str, const char *key);
|
||||
bool strbegin(const string &str, const char *key);
|
||||
|
||||
bool stribegin(const char *str, const char *key);
|
||||
bool stribegin(const string &str, const char *key);
|
||||
|
||||
bool strend(const char *str, const char *key);
|
||||
bool strend(const string &str, const char *key);
|
||||
|
||||
bool striend(const char *str, const char *key);
|
||||
bool striend(const string &str, const char *key);
|
||||
|
||||
void strltrim(char *str, const char *key);
|
||||
void strltrim(string &str, const char *key);
|
||||
|
||||
void striltrim(char *str, const char *key);
|
||||
void striltrim(string &str, const char *key);
|
||||
|
||||
void strrtrim(char *str, const char *key);
|
||||
void strrtrim(string &str, const char *key);
|
||||
|
||||
void strirtrim(char *str, const char *key);
|
||||
void strirtrim(string &str, const char *key);
|
||||
|
||||
void strtrim(char *str, const char *key);
|
||||
void strtrim(string &str, const char *key);
|
||||
|
||||
void stritrim(char *str, const char *key);
|
||||
void stritrim(string &str, const char *key);
|
||||
|
||||
void strquote(string &str);
|
||||
|
||||
bool strunquote(char *str);
|
||||
bool strunquote(string &str);
|
||||
|
||||
uint strhex(const char *str);
|
||||
uint strhex(const string &str);
|
||||
|
||||
uint strdec(const char *str);
|
||||
uint strdec(const string &str);
|
||||
|
||||
uint strbin(const char *str);
|
||||
uint strbin(const string &str);
|
||||
|
||||
char *utoa(char *str, uint num);
|
||||
string &utoa(string &str, uint num);
|
||||
|
||||
char *itoa(char *str, uint num);
|
||||
string &itoa(string &str, uint num);
|
||||
|
||||
char *htoa(char *str, uint num);
|
||||
string &htoa(string &str, uint num);
|
||||
|
||||
char *btoa(char *str, uint num);
|
||||
string &btoa(string &str, uint num);
|
||||
|
||||
bool strfread(string &str, const char *filename);
|
||||
|
||||
string strfmt(const char *fmt, int num);
|
||||
|
||||
int strmath(const char *str);
|
||||
int strmath(const string &str);
|
||||
|
||||
string &replace(string &str, const char *key, const char *token);
|
||||
string &replace(string &str, const char *key, const string &token);
|
||||
|
||||
string &qreplace(string &str, const char *key, const char *token);
|
||||
string &qreplace(string &str, const char *key, const string &token);
|
||||
|
||||
void split(stringarray &dest, const char *key, const char *src);
|
||||
void split(stringarray &dest, const char *key, const string &src);
|
||||
|
||||
void qsplit(stringarray &dest, const char *key, const char *src);
|
||||
void qsplit(stringarray &dest, const char *key, const string &src);
|
||||
|
||||
uint vsprintf(string &str, const char *s, va_list args);
|
||||
uint sprintf(string &str, const char *s, ...);
|
||||
|
||||
class string {
|
||||
public:
|
||||
char *s;
|
||||
uint size;
|
||||
void reserve(uint reqsize) {
|
||||
if(reqsize > size) {
|
||||
size = reqsize;
|
||||
s = (char*)realloc(s, size + 1);
|
||||
s[size] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(string &str) {
|
||||
::swap(s, str.s);
|
||||
::swap(size, str.size);
|
||||
}
|
||||
|
||||
string() {
|
||||
size = 16;
|
||||
s = (char*)malloc(size + 1);
|
||||
s[0] = 0;
|
||||
}
|
||||
|
||||
string(const char *str) {
|
||||
size = strlen(str);
|
||||
s = (char*)malloc(size + 1);
|
||||
strcpy(s, str);
|
||||
}
|
||||
|
||||
string(const string &str) {
|
||||
size = strlen(str);
|
||||
s = (char*)malloc(size + 1);
|
||||
strcpy(s, strptr(str));
|
||||
}
|
||||
|
||||
~string() { safe_free(s); }
|
||||
|
||||
operator const char*() const { return s; }
|
||||
const char* operator()() const { return s; }
|
||||
char& operator[](const uint);
|
||||
|
||||
string& operator=(const int);
|
||||
string& operator=(const char*);
|
||||
string& operator=(const string&);
|
||||
|
||||
string& operator<<(const int);
|
||||
string& operator<<(const char*);
|
||||
string& operator<<(const string&);
|
||||
|
||||
bool operator==(const char*);
|
||||
bool operator==(const string&);
|
||||
bool operator!=(const char*);
|
||||
bool operator!=(const string&);
|
||||
bool operator< (const char*);
|
||||
bool operator< (const string&);
|
||||
bool operator<=(const char*);
|
||||
bool operator<=(const string&);
|
||||
bool operator> (const char*);
|
||||
bool operator> (const string&);
|
||||
bool operator>=(const char*);
|
||||
bool operator>=(const string&);
|
||||
};
|
||||
|
||||
inline void swap(string &x, string &y) { x.swap(y); }
|
||||
|
||||
#endif //LIBSTRING_H
|
||||
@@ -1,11 +0,0 @@
|
||||
uint count(stringarray &str) {
|
||||
return str.size();
|
||||
}
|
||||
|
||||
int find(stringarray &str, const char *key) {
|
||||
for(uint i = 0; i < count(str); i++) {
|
||||
if(str[i] == key) { return i; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int find(stringarray &str, const string &key) { return find(str, strptr(key)); }
|
||||
@@ -1,5 +0,0 @@
|
||||
string strfmt(const char *fmt, int num) {
|
||||
string temp;
|
||||
sprintf(temp, fmt, num);
|
||||
return temp;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
char &string::operator[](const uint index) {
|
||||
reserve(index);
|
||||
return s[index];
|
||||
}
|
||||
|
||||
string &string::operator=(const int num) {
|
||||
strcpy(*this, strfmt("%d", num));
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator=(const char *str) {
|
||||
strcpy(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator=(const string &str) {
|
||||
strcpy(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator<<(const int num) {
|
||||
strcat(*this, strfmt("%d", num));
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator<<(const char* str) {
|
||||
strcat(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator<<(const string& str) {
|
||||
strcat(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool string::operator==(const char *str) { return strcmp(strptr(*this), str) == 0; }
|
||||
bool string::operator==(const string &str) { return strcmp(strptr(*this), strptr(str)) == 0; }
|
||||
bool string::operator!=(const char *str) { return strcmp(strptr(*this), str) != 0; }
|
||||
bool string::operator!=(const string &str) { return strcmp(strptr(*this), strptr(str)) != 0; }
|
||||
bool string::operator< (const char *str) { return strcmp(strptr(*this), str) < 0; }
|
||||
bool string::operator< (const string &str) { return strcmp(strptr(*this), strptr(str)) < 0; }
|
||||
bool string::operator<=(const char *str) { return strcmp(strptr(*this), str) <= 0; }
|
||||
bool string::operator<=(const string &str) { return strcmp(strptr(*this), strptr(str)) <= 0; }
|
||||
bool string::operator> (const char *str) { return strcmp(strptr(*this), str) > 0; }
|
||||
bool string::operator> (const string &str) { return strcmp(strptr(*this), strptr(str)) > 0; }
|
||||
bool string::operator>=(const char *str) { return strcmp(strptr(*this), str) >= 0; }
|
||||
bool string::operator>=(const string &str) { return strcmp(strptr(*this), strptr(str)) >= 0; }
|
||||
@@ -1,220 +0,0 @@
|
||||
uint vsprintf(string &str, const char *s, va_list args) {
|
||||
va_list temp;
|
||||
va_copy(temp, args);
|
||||
int length = vsnprintf(0, 0, s, temp);
|
||||
if(length < 0) length = 16 * 1024; //temp fix for non-C99-complaint vsnprintf
|
||||
va_end(temp);
|
||||
|
||||
str.reserve(length);
|
||||
|
||||
va_copy(temp, args);
|
||||
length = vsprintf(strptr(str), s, temp);
|
||||
va_end(temp);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
uint sprintf(string &str, const char *s, ...) {
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
uint length = vsprintf(str, s, args);
|
||||
va_end(args);
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
uint vsprintf(string &str, const char *s, va_list args) {
|
||||
bool leftalign;
|
||||
bool showbase;
|
||||
char positivesign;
|
||||
char pad;
|
||||
uint width;
|
||||
bool useprecision;
|
||||
uint precision;
|
||||
char modifier;
|
||||
char type;
|
||||
|
||||
uint32 vararg32;
|
||||
uint64 vararg64;
|
||||
char *varptr;
|
||||
char varstr[256];
|
||||
uint varstrlen;
|
||||
|
||||
strcpy(str, "");
|
||||
uint i = 0;
|
||||
while(s[i]) {
|
||||
if(s[i] != '%') {
|
||||
strcat(str, s[i++]);
|
||||
} else if(s[i + 1] == '%' || !s[i + 1]) {
|
||||
strcat(str, '%');
|
||||
} else { //s[i] == '%'
|
||||
//format: %[flags][width][.precision][modifiers]type
|
||||
i++;
|
||||
|
||||
//flags
|
||||
leftalign = false;
|
||||
positivesign = 0;
|
||||
showbase = false;
|
||||
|
||||
while(s[i]) {
|
||||
if(s[i] == '-') {
|
||||
leftalign = true;
|
||||
i++;
|
||||
} else if(s[i] == '+') {
|
||||
positivesign = '+';
|
||||
i++;
|
||||
} else if(s[i] == ' ') {
|
||||
positivesign = ' ';
|
||||
i++;
|
||||
} else if(s[i] == '#') {
|
||||
showbase = true;
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//zero padding
|
||||
if(s[i] == '0') {
|
||||
pad = '0';
|
||||
i++;
|
||||
} else {
|
||||
pad = ' ';
|
||||
}
|
||||
|
||||
//width
|
||||
width = 0;
|
||||
if(s[i] == '*') {
|
||||
width = va_arg(args, uint32);
|
||||
i++;
|
||||
} else {
|
||||
while(s[i]) {
|
||||
if(s[i] < '0' || s[i] > '9')break;
|
||||
width *= 10;
|
||||
width += s[i++] - '0';
|
||||
}
|
||||
}
|
||||
if(width == 0)width = 1;
|
||||
|
||||
//precision
|
||||
useprecision = false;
|
||||
precision = 0;
|
||||
if(s[i] == '.') {
|
||||
useprecision = true;
|
||||
i++;
|
||||
|
||||
if(s[i] == '*') {
|
||||
precision = va_arg(args, uint32);
|
||||
i++;
|
||||
} else {
|
||||
while(s[i]) {
|
||||
if(s[i] < '0' || s[i] > '9')break;
|
||||
precision *= 10;
|
||||
precision += s[i++] - '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if(precision == 0)precision = 1;
|
||||
|
||||
//modifier
|
||||
if(s[i] == 'h') {
|
||||
modifier = 'h';
|
||||
i++;
|
||||
} else if(s[i] == 'l') {
|
||||
modifier = 'l';
|
||||
i++;
|
||||
} else if(s[i] == 'L') {
|
||||
modifier = 'L';
|
||||
i++;
|
||||
}
|
||||
|
||||
//type
|
||||
type = s[i++];
|
||||
switch(type) {
|
||||
|
||||
case 'c': {
|
||||
//character
|
||||
vararg32 = va_arg(args, uint32);
|
||||
|
||||
if(leftalign == false) { while(width-- > 1)strcat(str, pad); }
|
||||
strcat(str, char(vararg32));
|
||||
if(leftalign == true) { while(width-- > 1)strcat(str, pad); }
|
||||
} break;
|
||||
|
||||
case 's': {
|
||||
//string
|
||||
varptr = va_arg(args, char*);
|
||||
|
||||
varstrlen = strlen(varptr);
|
||||
if(useprecision && precision < varstrlen)varstrlen = precision;
|
||||
if(leftalign == false) { while(width-- > varstrlen)strcat(str, pad); }
|
||||
uint index = 0;
|
||||
//todo: optimize to a fixed-width strcat
|
||||
while(index < varstrlen)strcat(str, varptr[index++]);
|
||||
if(leftalign == true) { while(width-- > varstrlen)strcat(str, pad); }
|
||||
} break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': {
|
||||
//signed integer
|
||||
vararg32 = va_arg(args, uint32);
|
||||
|
||||
if(type == 'd' || type == 'i') {
|
||||
itoa(varstr, vararg32);
|
||||
} else if(type == 'u') {
|
||||
utoa(varstr, vararg32);
|
||||
} else if(type == 'x') {
|
||||
htoa(varstr, vararg32);
|
||||
} else if(type == 'X') {
|
||||
uhtoa(varstr, vararg32);
|
||||
}
|
||||
|
||||
uint basestrlen = strlen(varstr);
|
||||
varstrlen = (useprecision && precision > basestrlen) ? precision : basestrlen;
|
||||
|
||||
if(type == 'd' || type == 'i') {
|
||||
if(int32(vararg32) >= 0 && positivesign) { varstrlen++; }
|
||||
}
|
||||
|
||||
if(type == 'x' || type == 'X') {
|
||||
if(showbase) { varstrlen += 2; }
|
||||
}
|
||||
|
||||
if(leftalign == false) { while(width-- > varstrlen)strcat(str, pad); }
|
||||
if(type == 'd' || type == 'i') {
|
||||
if(int32(vararg32) >= 0 && positivesign) { strcat(str, positivesign); }
|
||||
}
|
||||
if(type == 'x' || type == 'X') {
|
||||
if(showbase)strcat(str, (type == 'x') ? "0x" : "0X");
|
||||
}
|
||||
if(useprecision) {
|
||||
while(basestrlen < precision) { strcat(str, "0"); basestrlen++; }
|
||||
}
|
||||
strcat(str, varstr);
|
||||
if(leftalign == true) { while(width-- > varstrlen)strcat(str, pad); }
|
||||
} break;
|
||||
|
||||
case 'p': {
|
||||
//todo: add 64-bit pointer support
|
||||
vararg32 = va_arg(args, uint32);
|
||||
|
||||
strcpy(varstr, "00000000");
|
||||
uint index = 8;
|
||||
htoa(varstr + index, vararg32);
|
||||
varstrlen = strlen(varstr + index);
|
||||
index -= 8 - varstrlen;
|
||||
|
||||
if(leftalign == false) { while(width-- > 8)strcat(str, pad); }
|
||||
strcat(str, varstr + index);
|
||||
if(leftalign == true) { while(width-- > 8)strcat(str, pad); }
|
||||
} break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return strlen(str);
|
||||
}
|
||||
*/
|
||||
@@ -1,283 +0,0 @@
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include "libui_gtk.h"
|
||||
#include "libui_gtk_window.cpp"
|
||||
#include "libui_gtk_control.cpp"
|
||||
|
||||
namespace libui {
|
||||
|
||||
void init() {
|
||||
int argc = 1;
|
||||
char **argv;
|
||||
argv = (char**)malloc(1 * sizeof(char*));
|
||||
argv[0] = (char*)malloc(64 * sizeof(char));
|
||||
strcpy(argv[0], "./libui");
|
||||
//GTK+ insists you provide main()'s argc, argv parameters for
|
||||
//some special command-line processing options that are likely
|
||||
//never used by anything.
|
||||
//However, I insist on libui_init() not requiring arguments so
|
||||
//that it can be called from anywhere, including a global
|
||||
//constructor that is invoked before main() is reached.
|
||||
gtk_init(&argc, &argv);
|
||||
safe_free(argv[0]);
|
||||
safe_free(argv);
|
||||
}
|
||||
|
||||
void term() {
|
||||
}
|
||||
|
||||
bool run() {
|
||||
gtk_main_iteration_do(false);
|
||||
return events_pending();
|
||||
}
|
||||
|
||||
bool events_pending() {
|
||||
return gtk_events_pending();
|
||||
}
|
||||
|
||||
uint get_screen_width() { return gdk_screen_width(); }
|
||||
uint get_screen_height() { return gdk_screen_height(); }
|
||||
|
||||
//
|
||||
|
||||
bool file_load(Window *owner, char *filename, const char *filter, const char *path) {
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Load File",
|
||||
owner ? GTK_WINDOW(owner->info.window) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, (const gchar*)0);
|
||||
|
||||
if(path && strcmp(path, "")) {
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
}
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
strcpy(filename, fn);
|
||||
g_free(fn);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return strcmp(filename, ""); //return true if filename != ""
|
||||
}
|
||||
|
||||
bool file_save(Window *owner, char *filename, const char *filter, const char *path) {
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Save File",
|
||||
owner ? GTK_WINDOW(owner->info.window) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, (const gchar*)0);
|
||||
|
||||
if(path && strcmp(path, "")) {
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
}
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
strcpy(filename, fn);
|
||||
g_free(fn);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return strcmp(filename, ""); //return true if filename != ""
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint16 translate_key(uint key) {
|
||||
switch(key) {
|
||||
|
||||
case GDK_Escape: return keymap::esc;
|
||||
|
||||
case GDK_F1: return keymap::f1;
|
||||
case GDK_F2: return keymap::f2;
|
||||
case GDK_F3: return keymap::f3;
|
||||
case GDK_F4: return keymap::f4;
|
||||
case GDK_F5: return keymap::f5;
|
||||
case GDK_F6: return keymap::f6;
|
||||
case GDK_F7: return keymap::f7;
|
||||
case GDK_F8: return keymap::f8;
|
||||
case GDK_F9: return keymap::f9;
|
||||
case GDK_F10: return keymap::f10;
|
||||
case GDK_F11: return keymap::f11;
|
||||
case GDK_F12: return keymap::f12;
|
||||
|
||||
case GDK_Print: return keymap::print_screen;
|
||||
case GDK_Sys_Req: return keymap::sys_req;
|
||||
case GDK_Scroll_Lock: return keymap::scroll_lock;
|
||||
case GDK_Pause: return keymap::pause;
|
||||
case GDK_Break: return keymap::brk;
|
||||
|
||||
case GDK_grave: return keymap::grave;
|
||||
case GDK_asciitilde: return keymap::tilde;
|
||||
|
||||
case GDK_1: return keymap::num_1;
|
||||
case GDK_2: return keymap::num_2;
|
||||
case GDK_3: return keymap::num_3;
|
||||
case GDK_4: return keymap::num_4;
|
||||
case GDK_5: return keymap::num_5;
|
||||
case GDK_6: return keymap::num_6;
|
||||
case GDK_7: return keymap::num_7;
|
||||
case GDK_8: return keymap::num_8;
|
||||
case GDK_9: return keymap::num_9;
|
||||
case GDK_0: return keymap::num_0;
|
||||
|
||||
case GDK_exclam: return keymap::exclamation;
|
||||
case GDK_at: return keymap::at;
|
||||
case GDK_numbersign: return keymap::pound;
|
||||
case GDK_dollar: return keymap::dollar;
|
||||
case GDK_percent: return keymap::percent;
|
||||
case GDK_asciicircum: return keymap::power;
|
||||
case GDK_ampersand: return keymap::ampersand;
|
||||
case GDK_asterisk: return keymap::asterisk;
|
||||
case GDK_parenleft: return keymap::lparenthesis;
|
||||
case GDK_parenright: return keymap::rparenthesis;
|
||||
|
||||
case GDK_minus: return keymap::minus;
|
||||
case GDK_underscore: return keymap::underscore;
|
||||
case GDK_equal: return keymap::equal;
|
||||
case GDK_plus: return keymap::plus;
|
||||
case GDK_BackSpace: return keymap::backspace;
|
||||
|
||||
case GDK_Insert: return keymap::ins;
|
||||
case GDK_Delete: return keymap::del;
|
||||
case GDK_Home: return keymap::home;
|
||||
case GDK_End: return keymap::end;
|
||||
case GDK_Page_Up: return keymap::page_up;
|
||||
case GDK_Page_Down: return keymap::page_down;
|
||||
|
||||
case GDK_a: return keymap::a;
|
||||
case GDK_b: return keymap::b;
|
||||
case GDK_c: return keymap::c;
|
||||
case GDK_d: return keymap::d;
|
||||
case GDK_e: return keymap::e;
|
||||
case GDK_f: return keymap::f;
|
||||
case GDK_g: return keymap::g;
|
||||
case GDK_h: return keymap::h;
|
||||
case GDK_i: return keymap::i;
|
||||
case GDK_j: return keymap::j;
|
||||
case GDK_k: return keymap::k;
|
||||
case GDK_l: return keymap::l;
|
||||
case GDK_m: return keymap::m;
|
||||
case GDK_n: return keymap::n;
|
||||
case GDK_o: return keymap::o;
|
||||
case GDK_p: return keymap::p;
|
||||
case GDK_q: return keymap::q;
|
||||
case GDK_r: return keymap::r;
|
||||
case GDK_s: return keymap::s;
|
||||
case GDK_t: return keymap::t;
|
||||
case GDK_u: return keymap::u;
|
||||
case GDK_v: return keymap::v;
|
||||
case GDK_w: return keymap::w;
|
||||
case GDK_x: return keymap::x;
|
||||
case GDK_y: return keymap::y;
|
||||
case GDK_z: return keymap::z;
|
||||
|
||||
case GDK_A: return keymap::A;
|
||||
case GDK_B: return keymap::B;
|
||||
case GDK_C: return keymap::C;
|
||||
case GDK_D: return keymap::D;
|
||||
case GDK_E: return keymap::E;
|
||||
case GDK_F: return keymap::F;
|
||||
case GDK_G: return keymap::G;
|
||||
case GDK_H: return keymap::H;
|
||||
case GDK_I: return keymap::I;
|
||||
case GDK_J: return keymap::J;
|
||||
case GDK_K: return keymap::K;
|
||||
case GDK_L: return keymap::L;
|
||||
case GDK_M: return keymap::M;
|
||||
case GDK_N: return keymap::N;
|
||||
case GDK_O: return keymap::O;
|
||||
case GDK_P: return keymap::P;
|
||||
case GDK_Q: return keymap::Q;
|
||||
case GDK_R: return keymap::R;
|
||||
case GDK_S: return keymap::S;
|
||||
case GDK_T: return keymap::T;
|
||||
case GDK_U: return keymap::U;
|
||||
case GDK_V: return keymap::V;
|
||||
case GDK_W: return keymap::W;
|
||||
case GDK_X: return keymap::X;
|
||||
case GDK_Y: return keymap::Y;
|
||||
case GDK_Z: return keymap::Z;
|
||||
|
||||
case GDK_bracketleft: return keymap::lbracket;
|
||||
case GDK_bracketright: return keymap::rbracket;
|
||||
case GDK_backslash: return keymap::backslash;
|
||||
case GDK_semicolon: return keymap::semicolon;
|
||||
case GDK_apostrophe: return keymap::apostrophe;
|
||||
case GDK_comma: return keymap::comma;
|
||||
case GDK_period: return keymap::period;
|
||||
case GDK_slash: return keymap::slash;
|
||||
|
||||
case GDK_braceleft: return keymap::lbrace;
|
||||
case GDK_braceright: return keymap::rbrace;
|
||||
case GDK_bar: return keymap::pipe;
|
||||
case GDK_colon: return keymap::colon;
|
||||
case GDK_quotedbl: return keymap::quote;
|
||||
case GDK_less: return keymap::lcaret;
|
||||
case GDK_greater: return keymap::rcaret;
|
||||
case GDK_question: return keymap::question;
|
||||
|
||||
case GDK_KP_1: return keymap::kp_1;
|
||||
case GDK_KP_2: return keymap::kp_2;
|
||||
case GDK_KP_3: return keymap::kp_3;
|
||||
case GDK_KP_4: return keymap::kp_4;
|
||||
case GDK_KP_5: return keymap::kp_5;
|
||||
case GDK_KP_6: return keymap::kp_6;
|
||||
case GDK_KP_7: return keymap::kp_7;
|
||||
case GDK_KP_8: return keymap::kp_8;
|
||||
case GDK_KP_9: return keymap::kp_9;
|
||||
case GDK_KP_0: return keymap::kp_0;
|
||||
case GDK_KP_Decimal: return keymap::kp_decimal;
|
||||
|
||||
case GDK_KP_End: return keymap::kp_end;
|
||||
case GDK_KP_Down: return keymap::kp_down;
|
||||
case GDK_KP_Page_Down: return keymap::kp_page_down;
|
||||
case GDK_KP_Left: return keymap::kp_left;
|
||||
case GDK_KP_Begin: return keymap::kp_center;
|
||||
case GDK_KP_Right: return keymap::kp_right;
|
||||
case GDK_KP_Home: return keymap::kp_home;
|
||||
case GDK_KP_Up: return keymap::kp_up;
|
||||
case GDK_KP_Page_Up: return keymap::kp_page_up;
|
||||
case GDK_KP_Insert: return keymap::kp_insert;
|
||||
case GDK_KP_Delete: return keymap::kp_delete;
|
||||
|
||||
case GDK_KP_Add: return keymap::kp_plus;
|
||||
case GDK_KP_Subtract: return keymap::kp_minus;
|
||||
case GDK_KP_Multiply: return keymap::kp_mul;
|
||||
case GDK_KP_Divide: return keymap::kp_div;
|
||||
case GDK_KP_Enter: return keymap::kp_enter;
|
||||
|
||||
case GDK_Num_Lock: return keymap::num_lock;
|
||||
case GDK_Caps_Lock: return keymap::caps_lock;
|
||||
|
||||
case GDK_Up: return keymap::up;
|
||||
case GDK_Down: return keymap::down;
|
||||
case GDK_Left: return keymap::left;
|
||||
case GDK_Right: return keymap::right;
|
||||
|
||||
case GDK_Tab: return keymap::tab;
|
||||
case GDK_Return: return keymap::enter;
|
||||
case GDK_space: return keymap::space;
|
||||
|
||||
case GDK_Control_L: return keymap::lctrl;
|
||||
case GDK_Control_R: return keymap::rctrl;
|
||||
case GDK_Alt_L: return keymap::lalt;
|
||||
case GDK_Alt_R: return keymap::ralt;
|
||||
case GDK_Shift_L: return keymap::lshift;
|
||||
case GDK_Shift_R: return keymap::rshift;
|
||||
case GDK_Super_L: return keymap::lsuper;
|
||||
case GDK_Super_R: return keymap::rsuper;
|
||||
case GDK_Menu: return keymap::menu;
|
||||
|
||||
}
|
||||
|
||||
return keymap::none;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
libui_gtk ~byuu (2007-06-06)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBUI_H
|
||||
#define LIBUI_H
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libarray.h"
|
||||
#include "libvector.h"
|
||||
#include "libstring.h"
|
||||
#include "libkeymap.h"
|
||||
|
||||
//TODO: hide this if possible
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace libui {
|
||||
|
||||
class Window;
|
||||
#include "libui_gtk_control.h"
|
||||
|
||||
void init();
|
||||
void term();
|
||||
bool run();
|
||||
bool events_pending();
|
||||
|
||||
uint get_screen_width();
|
||||
uint get_screen_height();
|
||||
|
||||
bool file_load(Window *owner, char *filename, const char *filter, const char *path = "");
|
||||
bool file_save(Window *owner, char *filename, const char *filter, const char *path = "");
|
||||
|
||||
uint16 translate_key(uint key);
|
||||
|
||||
namespace Message {
|
||||
enum {
|
||||
Invalid = 0,
|
||||
Close,
|
||||
Block,
|
||||
KeyUp,
|
||||
KeyDown,
|
||||
Clicked,
|
||||
DoubleClicked,
|
||||
Changed,
|
||||
};
|
||||
};
|
||||
|
||||
class Window { public:
|
||||
enum Style {
|
||||
Center = 1,
|
||||
};
|
||||
|
||||
MenuBar menu;
|
||||
void create(uint style, uint width, uint height, const char *caption = "");
|
||||
void set_text(const char *str);
|
||||
void set_background_color(uint8 r, uint8 g, uint8 b);
|
||||
void focus();
|
||||
bool focused();
|
||||
void move(uint x, uint y);
|
||||
void resize(uint width, uint height);
|
||||
virtual void show();
|
||||
virtual void hide();
|
||||
void show(bool state);
|
||||
bool visible();
|
||||
void fullscreen();
|
||||
void unfullscreen();
|
||||
void fullscreen(bool state);
|
||||
bool is_fullscreen();
|
||||
|
||||
virtual bool message(uint id, uintptr_t param = 0) { return true; }
|
||||
|
||||
//private:
|
||||
struct {
|
||||
GtkWidget *window, *menubar;
|
||||
GtkWidget *vcontainer, *container;
|
||||
} info;
|
||||
|
||||
public:
|
||||
Window() {
|
||||
info.menubar = 0;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,676 +0,0 @@
|
||||
namespace libui {
|
||||
|
||||
/*****
|
||||
* Control
|
||||
*****/
|
||||
|
||||
void Control::move(uint x, uint y) {
|
||||
gtk_fixed_move(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
}
|
||||
|
||||
void Control::resize(uint width, uint height) {
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
}
|
||||
|
||||
void Control::focus() {
|
||||
gtk_widget_grab_focus(widget);
|
||||
}
|
||||
|
||||
void Control::show() {
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void Control::hide() {
|
||||
gtk_widget_hide(widget);
|
||||
}
|
||||
|
||||
void Control::show(bool state) {
|
||||
(state == true) ? show() : hide();
|
||||
}
|
||||
|
||||
bool Control::visible() {
|
||||
return GTK_WIDGET_VISIBLE(widget);
|
||||
}
|
||||
|
||||
void Control::enable() {
|
||||
gtk_widget_set_sensitive(widget, true);
|
||||
}
|
||||
|
||||
void Control::disable() {
|
||||
gtk_widget_set_sensitive(widget, false);
|
||||
}
|
||||
|
||||
void Control::enable(bool state) {
|
||||
(state == true) ? enable() : disable();
|
||||
}
|
||||
|
||||
bool Control::enabled() {
|
||||
return GTK_WIDGET_SENSITIVE(widget);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuBar
|
||||
*****/
|
||||
|
||||
void MenuBar::create(Window &r_owner) {
|
||||
type = ControlType::MenuBar;
|
||||
widget = r_owner.info.menubar;
|
||||
owner = &r_owner;
|
||||
show();
|
||||
}
|
||||
|
||||
void MenuBar::finish() {
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuGroup
|
||||
*****/
|
||||
|
||||
void MenuGroup::create(MenuBar &r_owner, const char *caption) {
|
||||
type = ControlType::MenuGroup;
|
||||
widget = gtk_menu_new();
|
||||
item = gtk_menu_item_new_with_label(caption ? caption : "?");
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.widget;
|
||||
}
|
||||
|
||||
void MenuGroup::create(MenuGroup &r_owner, const char *caption) {
|
||||
type = ControlType::MenuGroup;
|
||||
widget = gtk_menu_new();
|
||||
item = gtk_menu_item_new_with_label(caption ? caption : "?");
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.widget;
|
||||
}
|
||||
|
||||
void MenuGroup::finish() {
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), widget);
|
||||
gtk_menu_bar_append(parent, item);
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuItem
|
||||
*****/
|
||||
|
||||
void MenuItem::create(MenuGroup &r_owner, const char *caption) {
|
||||
type = ControlType::MenuItem;
|
||||
widget = gtk_menu_item_new_with_label(caption ? caption : "?");
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.widget;
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "activate",
|
||||
G_CALLBACK(libui_control_clicked), (gpointer)this);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuCheckItem
|
||||
*****/
|
||||
|
||||
void MenuCheckItem::create(MenuGroup &r_owner, const char *caption) {
|
||||
type = ControlType::MenuCheckItem;
|
||||
widget = gtk_check_menu_item_new_with_label(caption ? caption : "?");
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.widget;
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "activate",
|
||||
G_CALLBACK(libui_control_clicked), (gpointer)this);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void MenuCheckItem::check() {
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE);
|
||||
}
|
||||
|
||||
void MenuCheckItem::uncheck() {
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), FALSE);
|
||||
}
|
||||
|
||||
void MenuCheckItem::check(bool state) {
|
||||
(state == true) ? check() : uncheck();
|
||||
}
|
||||
|
||||
bool MenuCheckItem::checked() {
|
||||
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuRadioItem
|
||||
*****/
|
||||
|
||||
void MenuRadioItem::create(MenuGroup &r_owner, ControlGroup &list, const char *caption) {
|
||||
if(list.count() == 0)throw;
|
||||
type = ControlType::MenuRadioItem;
|
||||
widget = (&list[0] == this) ?
|
||||
gtk_radio_menu_item_new_with_label(0, caption ? caption : "?") :
|
||||
gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(list[0].widget), caption ? caption : "");
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.widget;
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "activate",
|
||||
G_CALLBACK(libui_control_clicked), (gpointer)this);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void MenuRadioItem::check() {
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE);
|
||||
}
|
||||
|
||||
bool MenuRadioItem::checked() {
|
||||
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuSeparator
|
||||
*****/
|
||||
|
||||
void MenuSeparator::create(MenuGroup &r_owner) {
|
||||
type = ControlType::MenuSeparator;
|
||||
widget = gtk_separator_menu_item_new();
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.widget;
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Panel
|
||||
*****/
|
||||
|
||||
void Panel::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Panel;
|
||||
widget = gtk_fixed_new();
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void Panel::attach(Window &window) {
|
||||
if(attached) { //detach existing child window, return to toplevel window
|
||||
gtk_widget_reparent(attached->info.vcontainer, attached->info.window);
|
||||
}
|
||||
attached = &window;
|
||||
window.hide();
|
||||
gtk_widget_reparent(window.info.vcontainer, widget);
|
||||
}
|
||||
|
||||
void Panel::detach() {
|
||||
if(attached) {
|
||||
gtk_widget_reparent(attached->info.vcontainer, attached->info.window);
|
||||
}
|
||||
attached = 0;
|
||||
}
|
||||
|
||||
/*****
|
||||
* Container
|
||||
*****/
|
||||
|
||||
void Container::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Container;
|
||||
widget = gtk_drawing_area_new();
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void Container::set_background_color(uint8 r, uint8 g, uint8 b) {
|
||||
GdkColor color;
|
||||
color.pixel = (r << 16) | (g << 8) | (b);
|
||||
color.red = (r << 8) | (r);
|
||||
color.green = (g << 8) | (g);
|
||||
color.blue = (b << 8) | (b);
|
||||
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &color);
|
||||
}
|
||||
|
||||
unsigned long Container::x_handle() {
|
||||
return GDK_WINDOW_XWINDOW(widget->window);
|
||||
}
|
||||
|
||||
GtkWidget *Container::handle() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
/*****
|
||||
* Canvas
|
||||
*
|
||||
* Note: for reasons that defy any notion of logic, the GTK+ developers decided to
|
||||
* store color in semi-reversed format (XBGR) rather than conventional format (XRGB).
|
||||
* This is not an endian issue.
|
||||
* As a result, we are forced to perform manual conversion to XBGR format, at the
|
||||
* cost of significant overhead.
|
||||
*****/
|
||||
|
||||
void libui_canvas_expose(GtkWidget *widget, GdkEventAny *any, Canvas *canvas) {
|
||||
uint32 *d = canvas->rbuffer;
|
||||
uint32 *s = canvas->buffer;
|
||||
for(uint y = widget->allocation.height; y; y--) {
|
||||
for(uint x = widget->allocation.width; x; x--) {
|
||||
uint32 p = *s++;
|
||||
*d++ = ((p << 16) & 0xff0000) + (p & 0x00ff00) + ((p >> 16) & 0x0000ff);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_draw_rgb_32_image(widget->window,
|
||||
widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
|
||||
0, 0, widget->allocation.width, widget->allocation.height,
|
||||
GDK_RGB_DITHER_NONE, (guchar*)canvas->rbuffer, canvas->pitch);
|
||||
}
|
||||
|
||||
void Canvas::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Canvas;
|
||||
widget = gtk_drawing_area_new();
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
|
||||
pitch = width * sizeof(uint32);
|
||||
rbuffer = (uint32*)malloc(pitch * height);
|
||||
buffer = (uint32*)malloc(pitch * height);
|
||||
memset(buffer, 0, pitch * height);
|
||||
memset(rbuffer, 0, pitch * height);
|
||||
g_signal_connect(G_OBJECT(widget), "expose_event", G_CALLBACK(libui_canvas_expose), this);
|
||||
}
|
||||
|
||||
void Canvas::redraw() {
|
||||
if(!widget->window)return;
|
||||
|
||||
GdkRectangle rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = widget->allocation.width;
|
||||
rect.height = widget->allocation.height;
|
||||
gdk_window_invalidate_rect(widget->window, &rect, true);
|
||||
}
|
||||
|
||||
Canvas::Canvas() {
|
||||
buffer = 0;
|
||||
}
|
||||
|
||||
Canvas::~Canvas() {
|
||||
safe_free(rbuffer);
|
||||
safe_free(buffer);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Frame
|
||||
*****/
|
||||
|
||||
void Frame::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Frame;
|
||||
widget = gtk_frame_new(caption ? caption : "");
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Label
|
||||
*****/
|
||||
|
||||
void Label::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Label;
|
||||
widget = gtk_label_new(caption ? caption : "");
|
||||
owner = &r_owner;
|
||||
gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.0);
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void Label::set_text(const char *str) {
|
||||
gtk_label_set_label(GTK_LABEL(widget), str);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Button
|
||||
*****/
|
||||
|
||||
void Button::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Button;
|
||||
widget = gtk_button_new_with_label(caption ? caption : "");
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(libui_control_clicked), (gpointer)this);
|
||||
}
|
||||
|
||||
void Button::set_text(const char *str) {
|
||||
gtk_button_set_label(GTK_BUTTON(widget), str);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Checkbox
|
||||
*****/
|
||||
|
||||
void Checkbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Checkbox;
|
||||
widget = gtk_check_button_new_with_label(caption ? caption : "");
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(libui_control_clicked), (gpointer)this);
|
||||
}
|
||||
|
||||
void Checkbox::check() {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
||||
}
|
||||
|
||||
void Checkbox::uncheck() {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
|
||||
}
|
||||
|
||||
void Checkbox::check(bool state) {
|
||||
(state == true) ? check() : uncheck();
|
||||
}
|
||||
|
||||
bool Checkbox::checked() {
|
||||
return (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE) ? true : false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* Radiobox
|
||||
*****/
|
||||
|
||||
void Radiobox::create(Window &r_owner, ControlGroup &group, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
if(group.count() == 0)throw;
|
||||
type = ControlType::Radiobox;
|
||||
widget = (&group[0] == this) ?
|
||||
gtk_radio_button_new_with_label(0, caption ? caption : "") :
|
||||
gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(group[0].widget), caption ? caption : "");
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(libui_control_clicked), (gpointer)this);
|
||||
}
|
||||
|
||||
void Radiobox::check() {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
|
||||
}
|
||||
|
||||
bool Radiobox::checked() {
|
||||
return (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE) ? true : false;
|
||||
}
|
||||
|
||||
/*****
|
||||
* Editbox
|
||||
*****/
|
||||
|
||||
void Editbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
owner = &r_owner;
|
||||
type = ControlType::Editbox;
|
||||
multiline = bool(style & Multiline);
|
||||
|
||||
if(multiline == false) {
|
||||
widget = gtk_entry_new();
|
||||
if(style & Editbox::Readonly) { gtk_entry_set_editable(GTK_ENTRY(widget), false); }
|
||||
gtk_entry_set_text(GTK_ENTRY(widget), caption ? caption : "");
|
||||
} else {
|
||||
GtkPolicyType hscroll = (style & Editbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Editbox::HorizontalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
GtkPolicyType vscroll = (style & Editbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Editbox::VerticalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
widget = gtk_scrolled_window_new(0, 0);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), hscroll, vscroll);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), GTK_SHADOW_ETCHED_IN);
|
||||
subwidget = gtk_text_view_new();
|
||||
gtk_container_add(GTK_CONTAINER(widget), subwidget);
|
||||
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subwidget));
|
||||
if(style & Editbox::Readonly) { gtk_text_view_set_editable(GTK_TEXT_VIEW(subwidget), false); }
|
||||
gtk_text_buffer_set_text(buffer, caption ? caption : "", -1);
|
||||
gtk_widget_show(subwidget);
|
||||
}
|
||||
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void Editbox::set_text(const char *str) {
|
||||
if(multiline == false) {
|
||||
gtk_entry_set_text(GTK_ENTRY(widget), str);
|
||||
} else {
|
||||
gtk_text_buffer_set_text(buffer, str, -1);
|
||||
}
|
||||
}
|
||||
|
||||
uint Editbox::get_text(char *str, uint length) {
|
||||
if(multiline == false) {
|
||||
const char *temp = gtk_entry_get_text(GTK_ENTRY(widget));
|
||||
return strlcpy(str, temp ? temp : "", length);
|
||||
} else {
|
||||
GtkTextIter start, end;
|
||||
gtk_text_buffer_get_start_iter(buffer, &start);
|
||||
gtk_text_buffer_get_end_iter(buffer, &end);
|
||||
return strlcpy(str, gtk_text_buffer_get_text(buffer, &start, &end, true), length);
|
||||
}
|
||||
}
|
||||
|
||||
/*****
|
||||
* Listbox
|
||||
*****/
|
||||
|
||||
/*****
|
||||
* GTK+'s implementation of list boxes was apparently someone's idea of a very, very cruel joke ...
|
||||
* Attempt to understand the below code at the risk of your own sanity.
|
||||
*****/
|
||||
|
||||
void Listbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *columns) {
|
||||
owner = &r_owner;
|
||||
type = ControlType::Listbox;
|
||||
|
||||
bool header = bool(style & Header);
|
||||
|
||||
stringarray list, part;
|
||||
split(part, "|", columns);
|
||||
|
||||
GType *v = (GType*)malloc(count(part) * sizeof(GType));
|
||||
for(uint i = 0; i < count(part); i++) { v[i] = G_TYPE_STRING; }
|
||||
store = gtk_list_store_newv(count(part), v);
|
||||
safe_free(v);
|
||||
|
||||
widget = gtk_scrolled_window_new(0, 0);
|
||||
GtkPolicyType hscroll = (style & Listbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Listbox::HorizontalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
GtkPolicyType vscroll = (style & Listbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Listbox::VerticalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), hscroll, vscroll);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), GTK_SHADOW_ETCHED_IN);
|
||||
subwidget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
|
||||
gtk_container_add(GTK_CONTAINER(widget), subwidget);
|
||||
g_object_unref(G_OBJECT(store));
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(subwidget);
|
||||
gtk_widget_show(widget);
|
||||
|
||||
split(list, "|", columns);
|
||||
//alternate colors for each listbox entry if there are multiple columns ...
|
||||
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(subwidget), (count(list) >= 2) ? true : false);
|
||||
for(uint i = 0; i < count(list); i++) {
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(strptr(list[i]), renderer, "text", i, 0);
|
||||
column_list[column_list.size()] = column;
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(subwidget), column);
|
||||
}
|
||||
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(subwidget), header);
|
||||
autosize_columns();
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(subwidget), "cursor-changed", G_CALLBACK(libui_control_changed), (gpointer)this);
|
||||
g_signal_connect_swapped(G_OBJECT(subwidget), "row-activated", G_CALLBACK(libui_control_double_clicked), (gpointer)this);
|
||||
}
|
||||
|
||||
void Listbox::autosize_columns() {
|
||||
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(subwidget));
|
||||
}
|
||||
|
||||
void Listbox::set_column_width(uint column, uint width) {
|
||||
gtk_tree_view_column_set_min_width(column_list[column], width);
|
||||
gtk_tree_view_column_set_max_width(column_list[column], width);
|
||||
}
|
||||
|
||||
void Listbox::add_item(const char *data) {
|
||||
stringarray part;
|
||||
split(part, "|", data);
|
||||
gtk_list_store_append(store, &iter);
|
||||
for(uint i = 0; i < count(part); i++) {
|
||||
gtk_list_store_set(store, &iter, i, strptr(part[i]), -1);
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::set_item(uint index, const char *data) {
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
|
||||
for(uint i = 0; i <= index; i++) {
|
||||
(i == 0) ?
|
||||
gtk_tree_model_get_iter_first(model, &iter) :
|
||||
gtk_tree_model_iter_next(model, &iter);
|
||||
}
|
||||
|
||||
stringarray part;
|
||||
split(part, "|", data);
|
||||
for(uint i = 0; i < count(part); i++) {
|
||||
gtk_list_store_set(store, &iter, i, strptr(part[i]), -1);
|
||||
}
|
||||
}
|
||||
|
||||
//... because gtk_tree_view_get_selected_row(GTK_TREE_VIEW(subwidget)) would be too easy ...
|
||||
int Listbox::get_selection() {
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subwidget));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) { return -1; }
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) { return 0; }
|
||||
for(uint i = 1; i < 100000; i++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) { return -1; }
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) { return i; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//... because gtk_tree_view_set_selected_row(GTK_TREE_VIEW(subwidget), index) would be too easy ...
|
||||
void Listbox::set_selection(int index) {
|
||||
int current = get_selection();
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subwidget));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
|
||||
gtk_tree_selection_unselect_all(selection);
|
||||
if(index < 0) { goto end; }
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; }
|
||||
if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
||||
for(uint i = 1; i < 100000; i++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; }
|
||||
if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
||||
}
|
||||
end:
|
||||
if(current != index) { owner->message(Message::Changed, (uintptr_t)this); }
|
||||
}
|
||||
|
||||
void Listbox::reset() {
|
||||
gtk_list_store_clear(GTK_LIST_STORE(store));
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(subwidget), GTK_TREE_MODEL(store));
|
||||
}
|
||||
|
||||
/*****
|
||||
* Combobox
|
||||
*****/
|
||||
|
||||
void Combobox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Combobox;
|
||||
widget = gtk_combo_box_new_text(); //gtk_combo_box_entry_new_text(); /* alternate style */
|
||||
owner = &r_owner;
|
||||
counter = 0;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void Combobox::add_item(const char *data) {
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(widget), data);
|
||||
if(counter++ == 0) { set_selection(0); }
|
||||
}
|
||||
|
||||
int Combobox::get_selection() {
|
||||
return gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
|
||||
}
|
||||
|
||||
void Combobox::set_selection(int index) {
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), index);
|
||||
}
|
||||
|
||||
void Combobox::reset() {
|
||||
if(counter == 0) { return; }
|
||||
for(int i = (counter - 1); i >= 0; i--) {
|
||||
gtk_combo_box_remove_text(GTK_COMBO_BOX(widget), i);
|
||||
}
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
/*****
|
||||
* Progressbar
|
||||
*****/
|
||||
|
||||
void Progressbar::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Progressbar;
|
||||
widget = gtk_progress_bar_new();
|
||||
owner = &r_owner;
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
}
|
||||
|
||||
void Progressbar::set_progress(uint progress) {
|
||||
progress = minmax<0, 100>(progress);
|
||||
double p = (double)progress / 100.0;
|
||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(widget), p);
|
||||
}
|
||||
|
||||
uint Progressbar::get_progress() {
|
||||
uint p = (uint)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(widget)) * 100.0);
|
||||
return (uint)minmax<0, 100>(p);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Slider
|
||||
*****/
|
||||
|
||||
void Slider::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, uint range) {
|
||||
type = ControlType::Slider;
|
||||
orientation = (style & Vertical) ? 1 : 0;
|
||||
|
||||
if(range < 1)range = 1;
|
||||
if(orientation == 0) {
|
||||
widget = gtk_hscale_new_with_range(0, range - 1, 1);
|
||||
} else {
|
||||
widget = gtk_vscale_new_with_range(0, range - 1, 1);
|
||||
}
|
||||
|
||||
owner = &r_owner;
|
||||
gtk_scale_set_draw_value(GTK_SCALE(widget), FALSE);
|
||||
gtk_widget_set_size_request(widget, width, height);
|
||||
gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y);
|
||||
gtk_widget_show(widget);
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "value-changed", G_CALLBACK(libui_control_changed), (gpointer)this);
|
||||
}
|
||||
|
||||
void Slider::set_position(uint position) {
|
||||
gtk_range_set_value(GTK_RANGE(widget), position);
|
||||
}
|
||||
|
||||
uint Slider::get_position() {
|
||||
return (int)gtk_range_get_value(GTK_RANGE(widget));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,265 +0,0 @@
|
||||
namespace ControlType {
|
||||
enum {
|
||||
Invalid,
|
||||
MenuBar,
|
||||
MenuGroup,
|
||||
MenuItem,
|
||||
MenuCheckItem,
|
||||
MenuRadioItem,
|
||||
MenuSeparator,
|
||||
Panel,
|
||||
Container,
|
||||
Canvas,
|
||||
Frame,
|
||||
Label,
|
||||
Button,
|
||||
Checkbox,
|
||||
Radiobox,
|
||||
Editbox,
|
||||
Listbox,
|
||||
Combobox,
|
||||
Progressbar,
|
||||
Slider,
|
||||
};
|
||||
};
|
||||
|
||||
class Control { public:
|
||||
uint type;
|
||||
void move(uint x, uint y);
|
||||
void resize(uint width, uint height);
|
||||
|
||||
void focus();
|
||||
|
||||
void show(bool state);
|
||||
void show();
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
void enable(bool state);
|
||||
void enable();
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
//protected:
|
||||
Window *owner;
|
||||
GtkWidget *widget;
|
||||
uint id;
|
||||
|
||||
public:
|
||||
Control() : owner(0), widget(0), id(0), type(ControlType::Invalid) {}
|
||||
};
|
||||
|
||||
class ControlGroup { public:
|
||||
uint count() { return list.size(); }
|
||||
void add(Control &control) { list[list.size()] = &control; }
|
||||
void reset() { list.reset(); }
|
||||
ControlGroup &operator=(ControlGroup &source) { list = source.list; return *this; }
|
||||
Control &operator[](int index) { return *list[index]; }
|
||||
|
||||
private:
|
||||
array<Control*> list;
|
||||
};
|
||||
|
||||
class MenuBar : public Control { public:
|
||||
void create(Window &owner);
|
||||
void finish();
|
||||
};
|
||||
|
||||
class MenuGroup : public Control { public:
|
||||
void create(MenuBar &owner, const char *caption);
|
||||
void create(MenuGroup &owner, const char *caption);
|
||||
void finish();
|
||||
|
||||
private:
|
||||
GtkWidget *parent, *item;
|
||||
};
|
||||
|
||||
class MenuItem : public Control { public:
|
||||
void create(MenuGroup &owner, const char *caption);
|
||||
|
||||
private:
|
||||
GtkWidget *parent;
|
||||
};
|
||||
|
||||
class MenuCheckItem : public Control { public:
|
||||
void create(MenuGroup &owner, const char *caption);
|
||||
void check();
|
||||
void uncheck();
|
||||
void check(bool state);
|
||||
bool checked();
|
||||
|
||||
private:
|
||||
GtkWidget *parent;
|
||||
};
|
||||
|
||||
class MenuRadioItem : public Control { public:
|
||||
void create(MenuGroup &owner, ControlGroup &list, const char *caption);
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
private:
|
||||
GtkWidget *parent;
|
||||
};
|
||||
|
||||
class MenuSeparator : public Control { public:
|
||||
void create(MenuGroup &owner);
|
||||
|
||||
private:
|
||||
GtkWidget *parent;
|
||||
};
|
||||
|
||||
class Panel : public Control { public:
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void attach(Window &window);
|
||||
void detach();
|
||||
|
||||
private:
|
||||
Window *attached;
|
||||
|
||||
public:
|
||||
Panel() : attached(0) {}
|
||||
};
|
||||
|
||||
class Container : public Control { public:
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void set_background_color(uint8 r, uint8 g, uint8 b);
|
||||
|
||||
//platform-dependent:
|
||||
unsigned long x_handle();
|
||||
GtkWidget *handle();
|
||||
};
|
||||
|
||||
class Canvas : public Control { public:
|
||||
uint32 *buffer;
|
||||
uint pitch;
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void redraw();
|
||||
Canvas();
|
||||
~Canvas();
|
||||
|
||||
private:
|
||||
uint32 *rbuffer;
|
||||
friend void libui_canvas_expose(GtkWidget *widget, GdkEventAny *any, Canvas *canvas);
|
||||
};
|
||||
|
||||
class Frame : public Control { public:
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
};
|
||||
|
||||
class Label : public Control { public:
|
||||
enum { ideal_height = 18 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void set_text(const char *str);
|
||||
};
|
||||
|
||||
class Button : public Control { public:
|
||||
enum { ideal_height = 30 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void set_text(const char *str);
|
||||
};
|
||||
|
||||
class Checkbox : public Control { public:
|
||||
enum { ideal_height = 18 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void check();
|
||||
void uncheck();
|
||||
void check(bool state);
|
||||
bool checked();
|
||||
};
|
||||
|
||||
class Radiobox : public Control { public:
|
||||
enum { ideal_height = 18 };
|
||||
void create(Window &owner, ControlGroup &group, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void check();
|
||||
bool checked();
|
||||
};
|
||||
|
||||
class Editbox : public Control { public:
|
||||
enum { ideal_height = 30 };
|
||||
enum {
|
||||
Multiline = (1 << 1),
|
||||
Readonly = (1 << 2),
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = (1 << 3),
|
||||
HorizontalScrollNever = (1 << 4),
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = (1 << 5),
|
||||
VerticalScrollNever = (1 << 6),
|
||||
};
|
||||
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void set_text(const char *str);
|
||||
uint get_text(char *str, uint length);
|
||||
|
||||
private:
|
||||
GtkWidget *subwidget;
|
||||
GtkTextBuffer *buffer;
|
||||
bool multiline;
|
||||
};
|
||||
|
||||
class Listbox : public Control { public:
|
||||
enum {
|
||||
Header = (1 << 1),
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = (1 << 2),
|
||||
HorizontalScrollNever = (1 << 3),
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = (1 << 4),
|
||||
VerticalScrollNever = (1 << 5),
|
||||
};
|
||||
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *columns = "");
|
||||
void autosize_columns();
|
||||
void set_column_width(uint column, uint width);
|
||||
void add_item(const char *data);
|
||||
void set_item(uint index, const char *data);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
GtkWidget *subwidget;
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
array<GtkTreeViewColumn*> column_list;
|
||||
GtkTreeIter iter;
|
||||
};
|
||||
|
||||
class Combobox : public Control { public:
|
||||
enum { ideal_height = 30 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void add_item(const char *data);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
uint counter;
|
||||
};
|
||||
|
||||
class Progressbar : public Control { public:
|
||||
enum { ideal_height = 30 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void set_progress(uint progress);
|
||||
uint get_progress();
|
||||
};
|
||||
|
||||
class Slider : public Control { public:
|
||||
enum { ideal_height = 25 };
|
||||
enum {
|
||||
Horizontal = 0,
|
||||
Vertical = 1,
|
||||
};
|
||||
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, uint range);
|
||||
void set_position(uint position);
|
||||
uint get_position();
|
||||
|
||||
private:
|
||||
bool orientation;
|
||||
};
|
||||
@@ -1,119 +0,0 @@
|
||||
namespace libui {
|
||||
|
||||
gint libui_window_close(GtkWidget *w, GdkEventAny *any, Window *window) {
|
||||
if(window) { return !window->message(Message::Close); }
|
||||
return FALSE; //destroy window by default
|
||||
}
|
||||
|
||||
gint libui_window_keydown(GtkWidget *w, GdkEventKey *key, Window *window) {
|
||||
if(window) { window->message(Message::KeyDown, libui::translate_key(key->keyval)); }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint libui_window_keyup(GtkWidget *w, GdkEventKey *key, Window *window) {
|
||||
if(window) { window->message(Message::KeyUp, libui::translate_key(key->keyval)); }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void libui_control_clicked(Control *control) {
|
||||
if(control && control->owner) { control->owner->message(Message::Clicked, (uintptr_t)control); }
|
||||
}
|
||||
|
||||
void libui_control_changed(Control *control) {
|
||||
if(control && control->owner) { control->owner->message(Message::Changed, (uintptr_t)control); }
|
||||
}
|
||||
|
||||
void libui_control_double_clicked(Control *control) {
|
||||
if(control && control->owner) { control->owner->message(Message::DoubleClicked, (uintptr_t)control); }
|
||||
}
|
||||
|
||||
void Window::create(uint style, uint width, uint height, const char *caption) {
|
||||
info.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title(GTK_WINDOW(info.window), caption ? caption : "");
|
||||
gtk_window_set_resizable(GTK_WINDOW(info.window), false);
|
||||
g_signal_connect(G_OBJECT(info.window), "delete_event", G_CALLBACK(libui_window_close), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(info.window), "key_press_event", G_CALLBACK(libui_window_keydown), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(info.window), "key_release_event", G_CALLBACK(libui_window_keyup), (gpointer)this);
|
||||
|
||||
if(style & Center) { gtk_window_set_position(GTK_WINDOW(info.window), GTK_WIN_POS_CENTER_ALWAYS); }
|
||||
|
||||
info.vcontainer = gtk_vbox_new(false, 0);
|
||||
gtk_container_add(GTK_CONTAINER(info.window), info.vcontainer);
|
||||
gtk_widget_show(info.vcontainer);
|
||||
|
||||
//always create menubar, only display it when MenuBar type is created
|
||||
//this is needed to setup box packing before menubar is defined
|
||||
info.menubar = gtk_menu_bar_new();
|
||||
gtk_box_pack_start(GTK_BOX(info.vcontainer), info.menubar, false, false, 0);
|
||||
|
||||
info.container = gtk_fixed_new();
|
||||
gtk_widget_set_size_request(info.container, width, height);
|
||||
gtk_box_pack_end(GTK_BOX(info.vcontainer), info.container, true, true, 0);
|
||||
gtk_widget_show(info.container);
|
||||
}
|
||||
|
||||
void Window::focus() {
|
||||
gtk_window_present(GTK_WINDOW(info.window));
|
||||
}
|
||||
|
||||
bool Window::focused() {
|
||||
return gtk_window_is_active(GTK_WINDOW(info.window));
|
||||
}
|
||||
|
||||
void Window::move(uint x, uint y) {
|
||||
//if window was centered before, GTK+ will ignore move requests,
|
||||
//therfore we must turn off auto-centering.
|
||||
gtk_window_set_position(GTK_WINDOW(info.window), GTK_WIN_POS_NONE);
|
||||
gtk_window_move(GTK_WINDOW(info.window), x, y);
|
||||
}
|
||||
|
||||
void Window::resize(uint width, uint height) {
|
||||
gtk_widget_set_size_request(info.container, width, height);
|
||||
}
|
||||
|
||||
void Window::show() {
|
||||
gtk_widget_show(info.window);
|
||||
}
|
||||
|
||||
void Window::hide() {
|
||||
gtk_widget_hide(info.window);
|
||||
}
|
||||
|
||||
void Window::show(bool state) {
|
||||
(state == true) ? show() : hide();
|
||||
}
|
||||
|
||||
bool Window::visible() {
|
||||
return GTK_WIDGET_VISIBLE(info.window);
|
||||
}
|
||||
|
||||
void Window::fullscreen() {
|
||||
gtk_window_fullscreen(GTK_WINDOW(info.window));
|
||||
}
|
||||
|
||||
void Window::unfullscreen() {
|
||||
gtk_window_unfullscreen(GTK_WINDOW(info.window));
|
||||
}
|
||||
|
||||
void Window::fullscreen(bool state) {
|
||||
(state == true) ? fullscreen() : unfullscreen();
|
||||
}
|
||||
|
||||
bool Window::is_fullscreen() {
|
||||
return false;
|
||||
};
|
||||
|
||||
void Window::set_text(const char *str) {
|
||||
gtk_window_set_title(GTK_WINDOW(info.window), str);
|
||||
}
|
||||
|
||||
void Window::set_background_color(uint8 r, uint8 g, uint8 b) {
|
||||
GdkColor color;
|
||||
color.pixel = (r << 16) | (g << 8) | (b);
|
||||
color.red = (r << 8) | (r);
|
||||
color.green = (g << 8) | (g);
|
||||
color.blue = (b << 8) | (b);
|
||||
gtk_widget_modify_bg(info.window, GTK_STATE_NORMAL, &color);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,239 +0,0 @@
|
||||
#define _WIN32_IE 0x0600
|
||||
|
||||
#include "libui_win.h"
|
||||
#include "libui_win_window.cpp"
|
||||
#include "libui_win_control.cpp"
|
||||
|
||||
namespace libui {
|
||||
|
||||
long __stdcall canvas_wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||
long __stdcall label_wndproc (HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
HFONT create_font(const char *name, uint size) {
|
||||
HDC hdc = GetDC(0);
|
||||
HFONT font = CreateFont(-MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72),
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, name);
|
||||
ReleaseDC(0, hdc);
|
||||
return font;
|
||||
}
|
||||
|
||||
void init() {
|
||||
InitCommonControls();
|
||||
|
||||
WNDCLASS wc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = libui_wndproc;
|
||||
wc.lpszClassName = "libui_class";
|
||||
wc.lpszMenuName = 0;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
RegisterClass(&wc);
|
||||
|
||||
font.variable = create_font("Tahoma", 8);
|
||||
font.fixed = create_font("Courier New", 8);
|
||||
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = canvas_wndproc;
|
||||
wc.lpszClassName = "canvas_class";
|
||||
wc.lpszMenuName = 0;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
RegisterClass(&wc);
|
||||
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = label_wndproc;
|
||||
wc.lpszClassName = "label_class";
|
||||
wc.lpszMenuName = 0;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
RegisterClass(&wc);
|
||||
}
|
||||
|
||||
void term() {
|
||||
}
|
||||
|
||||
bool run() {
|
||||
MSG msg;
|
||||
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return events_pending();
|
||||
}
|
||||
|
||||
bool events_pending() {
|
||||
MSG msg;
|
||||
return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
|
||||
}
|
||||
|
||||
uint get_screen_width() { return GetSystemMetrics(SM_CXSCREEN); }
|
||||
uint get_screen_height() { return GetSystemMetrics(SM_CYSCREEN); }
|
||||
|
||||
//
|
||||
|
||||
bool file_load(Window *owner, char *filename, const char *filter, const char *path) {
|
||||
string dir, f;
|
||||
strcpy(dir, path ? path : "");
|
||||
replace(dir, "/", "\\");
|
||||
|
||||
stringarray type, part;
|
||||
strcpy(f, "");
|
||||
split(type, "|", filter);
|
||||
for(int i = 0; i < count(type); i++) {
|
||||
split(part, ";", type[i]);
|
||||
if(count(part) != 2)continue;
|
||||
|
||||
strcat(f, part[0]);
|
||||
strcat(f, " (");
|
||||
strcat(f, part[1]);
|
||||
strcat(f, ")|");
|
||||
replace(part[1], ",", ";");
|
||||
strcat(f, part[1]);
|
||||
strcat(f, "|");
|
||||
}
|
||||
|
||||
char *pf = strptr(f);
|
||||
for(int i = strlen(pf) - 1; i >= 0; i--) {
|
||||
if(pf[i] == '|')pf[i] = '\0';
|
||||
}
|
||||
|
||||
OPENFILENAME ofn;
|
||||
strcpy(filename, "");
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = owner ? owner->info.hwnd : 0;
|
||||
ofn.lpstrFilter = pf;
|
||||
ofn.lpstrInitialDir = strptr(dir);
|
||||
ofn.lpstrFile = filename;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
||||
ofn.lpstrDefExt = "";
|
||||
|
||||
return GetOpenFileName(&ofn);
|
||||
}
|
||||
|
||||
bool file_save(Window *owner, char *filename, const char *filter, const char *path) {
|
||||
string dir, f;
|
||||
strcpy(dir, path ? path : "");
|
||||
replace(dir, "/", "\\");
|
||||
|
||||
stringarray type, part;
|
||||
strcpy(f, "");
|
||||
split(type, "|", filter);
|
||||
for(int i = 0; i < count(type); i++) {
|
||||
split(part, ";", type[i]);
|
||||
if(count(part) != 2)continue;
|
||||
|
||||
strcat(f, part[0]);
|
||||
strcat(f, " (");
|
||||
strcat(f, part[1]);
|
||||
strcat(f, ")|");
|
||||
replace(part[1], ",", ";");
|
||||
strcat(f, part[1]);
|
||||
strcat(f, "|");
|
||||
}
|
||||
|
||||
char *pf = strptr(f);
|
||||
for(int i = strlen(pf) - 1; i >= 0; i--) {
|
||||
if(pf[i] == '|')pf[i] = '\0';
|
||||
}
|
||||
|
||||
OPENFILENAME ofn;
|
||||
strcpy(filename, "");
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = owner ? owner->info.hwnd : 0;
|
||||
ofn.lpstrFilter = pf;
|
||||
ofn.lpstrInitialDir = strptr(dir);
|
||||
ofn.lpstrFile = filename;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
||||
ofn.lpstrDefExt = "";
|
||||
|
||||
return GetSaveFileName(&ofn);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint16 translate_key(uint key) {
|
||||
switch(key) {
|
||||
|
||||
case VK_ESCAPE: return keymap::esc;
|
||||
|
||||
case VK_F1: return keymap::f1;
|
||||
case VK_F2: return keymap::f2;
|
||||
case VK_F3: return keymap::f3;
|
||||
case VK_F4: return keymap::f4;
|
||||
case VK_F5: return keymap::f5;
|
||||
case VK_F6: return keymap::f6;
|
||||
case VK_F7: return keymap::f7;
|
||||
case VK_F8: return keymap::f8;
|
||||
case VK_F9: return keymap::f9;
|
||||
case VK_F10: return keymap::f10;
|
||||
case VK_F11: return keymap::f11;
|
||||
case VK_F12: return keymap::f12;
|
||||
|
||||
case VK_TAB: return keymap::tab;
|
||||
case VK_RETURN: return keymap::enter;
|
||||
case VK_SPACE: return keymap::space;
|
||||
|
||||
case '0': return keymap::num_0;
|
||||
case '1': return keymap::num_1;
|
||||
case '2': return keymap::num_2;
|
||||
case '3': return keymap::num_3;
|
||||
case '4': return keymap::num_4;
|
||||
case '5': return keymap::num_5;
|
||||
case '6': return keymap::num_6;
|
||||
case '7': return keymap::num_7;
|
||||
case '8': return keymap::num_8;
|
||||
case '9': return keymap::num_9;
|
||||
|
||||
case 'A': return keymap::a;
|
||||
case 'B': return keymap::b;
|
||||
case 'C': return keymap::c;
|
||||
case 'D': return keymap::d;
|
||||
case 'E': return keymap::e;
|
||||
case 'F': return keymap::f;
|
||||
case 'G': return keymap::g;
|
||||
case 'H': return keymap::h;
|
||||
case 'I': return keymap::i;
|
||||
case 'J': return keymap::j;
|
||||
case 'K': return keymap::k;
|
||||
case 'L': return keymap::l;
|
||||
case 'M': return keymap::m;
|
||||
case 'N': return keymap::n;
|
||||
case 'O': return keymap::o;
|
||||
case 'P': return keymap::p;
|
||||
case 'Q': return keymap::q;
|
||||
case 'R': return keymap::r;
|
||||
case 'S': return keymap::s;
|
||||
case 'T': return keymap::t;
|
||||
case 'U': return keymap::u;
|
||||
case 'V': return keymap::v;
|
||||
case 'W': return keymap::w;
|
||||
case 'X': return keymap::x;
|
||||
case 'Y': return keymap::y;
|
||||
case 'Z': return keymap::z;
|
||||
|
||||
case VK_UP: return keymap::up;
|
||||
case VK_DOWN: return keymap::down;
|
||||
case VK_LEFT: return keymap::left;
|
||||
case VK_RIGHT: return keymap::right;
|
||||
|
||||
}
|
||||
return keymap::none;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
libui_win ~byuu (2007-06-10)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBUI_H
|
||||
#define LIBUI_H
|
||||
|
||||
#include "libbase.h"
|
||||
#include "libarray.h"
|
||||
#include "libvector.h"
|
||||
#include "libstring.h"
|
||||
#include "libkeymap.h"
|
||||
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
#define WINVER 0x0500
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
namespace libui {
|
||||
|
||||
class Window;
|
||||
#include "libui_win_control.h"
|
||||
|
||||
void init();
|
||||
void term();
|
||||
bool run();
|
||||
bool events_pending();
|
||||
|
||||
uint get_screen_width();
|
||||
uint get_screen_height();
|
||||
|
||||
bool file_load(Window *owner, char *filename, const char *filter, const char *path = "");
|
||||
bool file_save(Window *owner, char *filename, const char *filter, const char *path = "");
|
||||
|
||||
uint16 translate_key(uint key);
|
||||
|
||||
namespace Message {
|
||||
enum {
|
||||
Invalid = 0,
|
||||
Close,
|
||||
Block,
|
||||
KeyUp,
|
||||
KeyDown,
|
||||
Clicked,
|
||||
DoubleClicked,
|
||||
Changed,
|
||||
};
|
||||
};
|
||||
|
||||
class Window { public:
|
||||
enum Style {
|
||||
Center = 1,
|
||||
};
|
||||
|
||||
MenuBar menu;
|
||||
void create(uint style, uint width, uint height, const char *caption = "");
|
||||
void set_text(const char *str, ...);
|
||||
void set_background_color(uint8 r, uint8 g, uint8 b);
|
||||
void focus();
|
||||
bool focused();
|
||||
void move(uint x, uint y);
|
||||
void resize(uint width, uint height);
|
||||
virtual void show();
|
||||
virtual void hide();
|
||||
void show(bool state);
|
||||
bool visible();
|
||||
void fullscreen();
|
||||
void unfullscreen();
|
||||
void fullscreen(bool state);
|
||||
bool is_fullscreen();
|
||||
|
||||
virtual bool message(uint id, uintptr_t param = 0) { return true; }
|
||||
|
||||
void move(Control &control, uint x, uint y);
|
||||
void attach(Control &control);
|
||||
|
||||
Window();
|
||||
|
||||
//platform-dependent:
|
||||
HWND handle();
|
||||
|
||||
//private:
|
||||
struct {
|
||||
uint width, height;
|
||||
bool fullscreen;
|
||||
|
||||
HWND hwnd;
|
||||
HWND hwnd_resize;
|
||||
HBRUSH background;
|
||||
HMENU menubar;
|
||||
bool center;
|
||||
array<Control*> control;
|
||||
uint control_index;
|
||||
|
||||
array<MenuRadioItem*> menu_check_list;
|
||||
} info;
|
||||
long wndproc(HWND hwnd, uint msg, WPARAM wparam, LPARAM lparam);
|
||||
};
|
||||
|
||||
//platform-dependent:
|
||||
|
||||
static uint window_count = 0;
|
||||
|
||||
static struct {
|
||||
HFONT variable;
|
||||
HFONT fixed;
|
||||
} font;
|
||||
|
||||
HFONT create_font(const char *name, uint size);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,710 +0,0 @@
|
||||
namespace libui {
|
||||
|
||||
/*****
|
||||
* Control
|
||||
*****/
|
||||
|
||||
void Control::move(uint x, uint y) {
|
||||
SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
||||
}
|
||||
|
||||
void Control::resize(uint width, uint height) {
|
||||
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
|
||||
}
|
||||
|
||||
void Control::focus() {
|
||||
if(hwnd) { SetFocus(hwnd); }
|
||||
}
|
||||
|
||||
void Control::show() {
|
||||
ShowWindow(hwnd, SW_NORMAL);
|
||||
}
|
||||
|
||||
void Control::hide() {
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
}
|
||||
|
||||
void Control::show(bool state) {
|
||||
(state == true) ? show() : hide();
|
||||
}
|
||||
|
||||
bool Control::visible() {
|
||||
return (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) ? true : false;
|
||||
}
|
||||
|
||||
void Control::enable() {
|
||||
EnableWindow(hwnd, true);
|
||||
}
|
||||
|
||||
void Control::disable() {
|
||||
EnableWindow(hwnd, false);
|
||||
}
|
||||
|
||||
void Control::enable(bool state) {
|
||||
(state == true) ? enable() : disable();
|
||||
}
|
||||
|
||||
bool Control::enabled() {
|
||||
return !(GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuBar
|
||||
*****/
|
||||
|
||||
void MenuBar::create(Window &r_owner) {
|
||||
type = ControlType::MenuBar;
|
||||
group = CreateMenu();
|
||||
r_owner.attach(*this);
|
||||
owner->info.menu_check_list.reset();
|
||||
}
|
||||
|
||||
void MenuBar::finish() {
|
||||
show();
|
||||
|
||||
//check all menu radio items that need to be ...
|
||||
for(uint i = 0; i < owner->info.menu_check_list.size(); i++) {
|
||||
CheckMenuItem(owner->info.menu_check_list[i]->parent, owner->info.menu_check_list[i]->id, MF_CHECKED);
|
||||
}
|
||||
owner->info.menu_check_list.reset();
|
||||
}
|
||||
|
||||
void MenuBar::show() {
|
||||
SetMenu(owner->info.hwnd_resize, group);
|
||||
SetMenu(owner->info.hwnd, group);
|
||||
owner->resize(owner->info.width, owner->info.height);
|
||||
}
|
||||
|
||||
void MenuBar::hide() {
|
||||
SetMenu(owner->info.hwnd_resize, 0);
|
||||
SetMenu(owner->info.hwnd, 0);
|
||||
owner->resize(owner->info.width, owner->info.height);
|
||||
}
|
||||
|
||||
void MenuBar::show(bool state) {
|
||||
(state == true) ? show() : hide();
|
||||
}
|
||||
|
||||
bool MenuBar::visible() {
|
||||
return GetMenu(owner->info.hwnd);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuGroup
|
||||
*****/
|
||||
|
||||
void MenuGroup::create(MenuBar &r_owner, const char *_caption) {
|
||||
type = ControlType::MenuGroup;
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.group;
|
||||
group = CreatePopupMenu();
|
||||
caption = strdup(_caption);
|
||||
owner->attach(*this);
|
||||
}
|
||||
|
||||
void MenuGroup::create(MenuGroup &r_owner, const char *_caption) {
|
||||
type = ControlType::MenuGroup;
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.group;
|
||||
group = CreatePopupMenu();
|
||||
caption = strdup(_caption);
|
||||
owner->attach(*this);
|
||||
}
|
||||
|
||||
void MenuGroup::finish() {
|
||||
AppendMenu(parent, MF_STRING | MF_POPUP, (uint)group, caption);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuItem
|
||||
*****/
|
||||
|
||||
void MenuItem::create(MenuGroup &r_owner, const char *caption) {
|
||||
type = ControlType::MenuItem;
|
||||
owner = r_owner.owner;
|
||||
owner->attach(*this);
|
||||
AppendMenu(r_owner.group, MF_STRING, (uint)id, caption);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuCheckItem
|
||||
*****/
|
||||
|
||||
void MenuCheckItem::create(MenuGroup &r_owner, const char *caption) {
|
||||
type = ControlType::MenuCheckItem;
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.group;
|
||||
owner->attach(*this);
|
||||
AppendMenu(r_owner.group, MF_STRING, (uint)id, caption);
|
||||
}
|
||||
|
||||
void MenuCheckItem::check() {
|
||||
if(checked() == true)return;
|
||||
CheckMenuItem(parent, id, MF_CHECKED);
|
||||
owner->message(Message::Clicked, (uintptr_t)this);
|
||||
}
|
||||
|
||||
void MenuCheckItem::uncheck() {
|
||||
if(checked() == false)return;
|
||||
CheckMenuItem(parent, id, MF_UNCHECKED);
|
||||
owner->message(Message::Clicked, (uintptr_t)this);
|
||||
}
|
||||
|
||||
void MenuCheckItem::check(bool state) {
|
||||
(state == true) ? check() : uncheck();
|
||||
}
|
||||
|
||||
bool MenuCheckItem::checked() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, id, false, &info);
|
||||
return (info.fState & MFS_CHECKED);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuRadioItem
|
||||
*****/
|
||||
|
||||
void MenuRadioItem::create(MenuGroup &r_owner, ControlGroup &list, const char *caption) {
|
||||
if(list.count() == 0)throw;
|
||||
type = ControlType::MenuRadioItem;
|
||||
owner = r_owner.owner;
|
||||
parent = r_owner.group;
|
||||
owner->attach(*this);
|
||||
AppendMenu(r_owner.group, MF_STRING, (uint)id, caption);
|
||||
group = list;
|
||||
if(&group[0] == this) { owner->info.menu_check_list[owner->info.menu_check_list.size()] = this; }
|
||||
}
|
||||
|
||||
void MenuRadioItem::check() {
|
||||
if(checked() == true)return;
|
||||
//uncheck all items in group except for current item ...
|
||||
for(uint i = 0; i < group.count(); i++) {
|
||||
CheckMenuItem(parent, group[i].id, (id == group[i].id) ? MF_CHECKED : MF_UNCHECKED);
|
||||
}
|
||||
owner->message(Message::Clicked, (uintptr_t)this);
|
||||
}
|
||||
|
||||
bool MenuRadioItem::checked() {
|
||||
MENUITEMINFO info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(parent, id, false, &info);
|
||||
return (info.fState & MFS_CHECKED);
|
||||
}
|
||||
|
||||
/*****
|
||||
* MenuSeparator
|
||||
*****/
|
||||
|
||||
void MenuSeparator::create(MenuGroup &r_owner) {
|
||||
AppendMenu(r_owner.group, MF_SEPARATOR, 0, "");
|
||||
}
|
||||
|
||||
/*****
|
||||
* Panel
|
||||
*****/
|
||||
|
||||
void Panel::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Panel;
|
||||
hwnd = CreateWindow("libui_class", "", WS_CHILD | WS_VISIBLE,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Panel::attach(Window &window) {
|
||||
if(attached) { detach(); }
|
||||
attached = &window;
|
||||
SetParent(attached->info.hwnd, hwnd);
|
||||
SetWindowLong(attached->info.hwnd, GWL_STYLE, WS_CHILD);
|
||||
SetWindowPos(attached->info.hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE);
|
||||
ShowWindow(attached->info.hwnd, SW_NORMAL);
|
||||
}
|
||||
|
||||
void Panel::detach() {
|
||||
if(!attached) { return; }
|
||||
ShowWindow(attached->info.hwnd, SW_HIDE);
|
||||
SetWindowLong(attached->info.hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX);
|
||||
SetParent(attached->info.hwnd, NULL);
|
||||
attached = 0;
|
||||
}
|
||||
|
||||
/*****
|
||||
* Container
|
||||
*****/
|
||||
|
||||
void Container::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Container;
|
||||
|
||||
char classname[4096];
|
||||
sprintf(classname, "libui_class_%d", window_count++);
|
||||
WNDCLASS wc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = libui_wndproc;
|
||||
wc.lpszClassName = classname;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
RegisterClass(&wc);
|
||||
|
||||
hwnd = CreateWindow(classname, "", WS_CHILD | WS_VISIBLE,
|
||||
0, 0, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
}
|
||||
|
||||
void Container::set_background_color(uint8 r, uint8 g, uint8 b) {
|
||||
HBRUSH old_brush = background;
|
||||
background = (HBRUSH)CreateSolidBrush(RGB(r, g, b));
|
||||
SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)background);
|
||||
InvalidateRect(hwnd, 0, TRUE);
|
||||
if(old_brush) { DeleteObject((HGDIOBJ)old_brush); }
|
||||
}
|
||||
|
||||
HWND Container::handle() {
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
Container::Container() {
|
||||
background = 0;
|
||||
}
|
||||
|
||||
/*****
|
||||
* Canvas
|
||||
*****/
|
||||
|
||||
long __stdcall canvas_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
switch(msg) {
|
||||
|
||||
case WM_PAINT: {
|
||||
Canvas *canvas = (Canvas*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
if(canvas) { canvas->blit(); }
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
void Canvas::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
_w = width;
|
||||
_h = height;
|
||||
|
||||
type = ControlType::Canvas;
|
||||
hwnd = CreateWindow("canvas_class", "", WS_CHILD | WS_VISIBLE,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
|
||||
pitch = width * sizeof(uint32);
|
||||
buffer = (uint32*)malloc(pitch * height);
|
||||
memset(buffer, 0, pitch * height);
|
||||
|
||||
memset(&bmi, 0, sizeof(BITMAPINFO));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = width;
|
||||
bmi.bmiHeader.biHeight = -height; //use negative height to tell GDI not to flip bitmap vertically
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = pitch * height;
|
||||
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Canvas::blit() {
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(hwnd, &ps);
|
||||
SetDIBitsToDevice(ps.hdc, 0, 0, _w, _h, 0, 0, 0, _h, (void*)buffer, &bmi, DIB_RGB_COLORS);
|
||||
EndPaint(hwnd, &ps);
|
||||
}
|
||||
|
||||
void Canvas::redraw() {
|
||||
InvalidateRect(hwnd, 0, FALSE);
|
||||
}
|
||||
|
||||
Canvas::Canvas() {
|
||||
buffer = 0;
|
||||
}
|
||||
|
||||
Canvas::~Canvas() {
|
||||
safe_free(buffer);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Frame
|
||||
*****/
|
||||
|
||||
void Frame::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Frame;
|
||||
hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Label
|
||||
*****/
|
||||
|
||||
long __stdcall label_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
switch(msg) {
|
||||
|
||||
case WM_PAINT: {
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(hwnd, &ps);
|
||||
RECT rc;
|
||||
char t[4096];
|
||||
GetWindowText(hwnd, t, 4095); //TODO: use internal buffer, so length is not limited ...
|
||||
GetClientRect(hwnd, &rc);
|
||||
SetTextColor(ps.hdc, RGB(0, 0, 0));
|
||||
SetBkMode(ps.hdc, TRANSPARENT);
|
||||
SelectObject(ps.hdc, (HGDIOBJ)libui::font.variable);
|
||||
//center text if text height < control height, otherwise draw from top left corner
|
||||
RECT trc;
|
||||
GetClientRect(hwnd, &trc);
|
||||
DrawText(ps.hdc, t, strlen(t), &trc, DT_CALCRECT);
|
||||
if(trc.bottom < rc.bottom) {
|
||||
rc.top = (rc.bottom - trc.bottom) / 2;
|
||||
rc.bottom = rc.top + trc.bottom;
|
||||
}
|
||||
//
|
||||
DrawText(ps.hdc, t, strlen(t), &rc, DT_END_ELLIPSIS | DT_NOPREFIX);
|
||||
EndPaint(hwnd, &ps);
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
void Label::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
string t;
|
||||
strcpy(t, caption ? caption : "");
|
||||
replace(t, "\r", "");
|
||||
replace(t, "\n", "\r\n");
|
||||
|
||||
type = ControlType::Label;
|
||||
hwnd = CreateWindow("label_class", strptr(t), WS_CHILD | WS_VISIBLE,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Label::set_text(const char *str, ...) {
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
string temp;
|
||||
vsprintf(temp, str, args);
|
||||
va_end(args);
|
||||
SetWindowText(hwnd, strptr(temp));
|
||||
InvalidateRect(hwnd, 0, TRUE);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Button
|
||||
*****/
|
||||
|
||||
void Button::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Button;
|
||||
hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Checkbox
|
||||
*****/
|
||||
|
||||
void Checkbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Checkbox;
|
||||
hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Checkbox::check() {
|
||||
if(checked() == true)return;
|
||||
SendMessage(hwnd, BM_SETCHECK, (WPARAM)TRUE, 0);
|
||||
owner->message(Message::Clicked, (uintptr_t)this);
|
||||
}
|
||||
|
||||
void Checkbox::uncheck() {
|
||||
if(checked() == false)return;
|
||||
SendMessage(hwnd, BM_SETCHECK, (WPARAM)FALSE, 0);
|
||||
owner->message(Message::Clicked, (uintptr_t)this);
|
||||
}
|
||||
|
||||
void Checkbox::check(bool state) {
|
||||
(state == true) ? check() : uncheck();
|
||||
}
|
||||
|
||||
bool Checkbox::checked() {
|
||||
return SendMessage(hwnd, BM_GETCHECK, 0, 0);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Radiobox
|
||||
*****/
|
||||
|
||||
void Radiobox::create(Window &r_owner, ControlGroup &list, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
if(list.count() == 0)throw;
|
||||
type = ControlType::Radiobox;
|
||||
group = list;
|
||||
hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
r_owner.attach(*this);
|
||||
if(this == &group[0])check();
|
||||
}
|
||||
|
||||
void Radiobox::check() {
|
||||
if(checked() == true)return;
|
||||
for(uint i = 0; i < group.count(); i++) {
|
||||
SendMessage(group[i].hwnd, BM_SETCHECK, (group[i].hwnd == hwnd) ? (WPARAM)TRUE : (WPARAM)FALSE, 0);
|
||||
}
|
||||
owner->message(Message::Clicked, (uintptr_t)this);
|
||||
}
|
||||
|
||||
bool Radiobox::checked() {
|
||||
return SendMessage(hwnd, BM_GETCHECK, 0, 0);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Editbox
|
||||
*****/
|
||||
|
||||
void Editbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) {
|
||||
type = ControlType::Editbox;
|
||||
multiline = (style & Multiline);
|
||||
readonly = (style & Readonly);
|
||||
vscroll = false;
|
||||
hscroll = false;
|
||||
|
||||
uint hscroll = (style & HorizontalScrollAlways) ? WS_HSCROLL :
|
||||
(style & HorizontalScrollNever) ? 0 :
|
||||
ES_AUTOHSCROLL;
|
||||
uint vscroll = (style & VerticalScrollAlways) ? WS_VSCROLL :
|
||||
(style & VerticalScrollNever) ? 0 :
|
||||
ES_AUTOVSCROLL;
|
||||
|
||||
string data = caption;
|
||||
replace(data, "\r", "");
|
||||
replace(data, "\n", "\r\n");
|
||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", strptr(data),
|
||||
WS_CHILD | WS_VISIBLE | vscroll | hscroll |
|
||||
(multiline == true ? ES_MULTILINE : 0) |
|
||||
(readonly == true ? ES_READONLY : 0),
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Editbox::set_text(const char *str, ...) {
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
string data;
|
||||
vsprintf(data, str, args);
|
||||
va_end(args);
|
||||
|
||||
replace(data, "\r", "");
|
||||
replace(data, "\n", "\r\n");
|
||||
SetWindowText(hwnd, strptr(data));
|
||||
}
|
||||
|
||||
uint Editbox::get_text(char *str, uint length) {
|
||||
GetWindowText(hwnd, str, length);
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Listbox
|
||||
*****/
|
||||
|
||||
void Listbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *columns) {
|
||||
stringarray part;
|
||||
header = (style & Header);
|
||||
|
||||
uint hscroll = (style & HorizontalScrollAlways) ? WS_HSCROLL :
|
||||
(style & HorizontalScrollNever) ? 0 :
|
||||
0;
|
||||
uint vscroll = (style & VerticalScrollAlways) ? WS_VSCROLL :
|
||||
(style & VerticalScrollNever) ? 0 :
|
||||
0;
|
||||
|
||||
type = ControlType::Listbox;
|
||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, "",
|
||||
WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | vscroll | hscroll |
|
||||
(header == true ? 0 : LVS_NOCOLUMNHEADER),
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT);
|
||||
|
||||
split(part, "|", columns);
|
||||
column_count = count(part);
|
||||
for(uint i = 0; i < column_count; i++) {
|
||||
LVCOLUMN column;
|
||||
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM;
|
||||
column.fmt = LVCFMT_LEFT;
|
||||
column.iSubItem = count(part);
|
||||
column.pszText = (LPSTR)strptr(part[i]);
|
||||
ListView_InsertColumn(hwnd, i, &column);
|
||||
}
|
||||
|
||||
autosize_columns();
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Listbox::autosize_columns() {
|
||||
for(uint i = 0; i < column_count; i++) {
|
||||
ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE_USEHEADER);
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::set_column_width(uint column, uint width) {
|
||||
ListView_SetColumnWidth(hwnd, column, width);
|
||||
}
|
||||
|
||||
void Listbox::add_item(const char *data, ...) {
|
||||
va_list args;
|
||||
va_start(args, data);
|
||||
string temp;
|
||||
vsprintf(temp, data, args);
|
||||
va_end(args);
|
||||
|
||||
stringarray part;
|
||||
split(part, "|", temp);
|
||||
|
||||
LVITEM item;
|
||||
uint pos = ListView_GetItemCount(hwnd);
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = pos;
|
||||
item.iSubItem = 0;
|
||||
item.pszText = (LPSTR)strptr(part[0]);
|
||||
ListView_InsertItem(hwnd, &item);
|
||||
|
||||
for(uint i = 1; i < count(part); i++) {
|
||||
ListView_SetItemText(hwnd, pos, i, (LPSTR)strptr(part[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::set_item(uint index, const char *data, ...) {
|
||||
va_list args;
|
||||
va_start(args, data);
|
||||
string temp;
|
||||
vsprintf(temp, data, args);
|
||||
va_end(args);
|
||||
|
||||
stringarray part;
|
||||
split(part, "|", temp);
|
||||
|
||||
for(uint i = 0; i < count(part); i++) {
|
||||
ListView_SetItemText(hwnd, index, i, strptr(part[i]));
|
||||
}
|
||||
}
|
||||
|
||||
int Listbox::get_selection() {
|
||||
uint count = ListView_GetItemCount(hwnd);
|
||||
for(uint i = 0; i < count; i++) {
|
||||
if(ListView_GetItemState(hwnd, i, LVIS_SELECTED))return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Listbox::set_selection(int index) {
|
||||
uint count = ListView_GetItemCount(hwnd);
|
||||
for(uint i = 0; i < count; i++) {
|
||||
ListView_SetItemState(hwnd, i, LVIS_FOCUSED, (i == index) ? LVIS_FOCUSED : 0);
|
||||
ListView_SetItemState(hwnd, i, LVIS_SELECTED, (i == index) ? LVIS_SELECTED : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::reset() {
|
||||
ListView_DeleteAllItems(hwnd);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Combobox
|
||||
*****/
|
||||
|
||||
void Combobox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Combobox;
|
||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "COMBOBOX", "",
|
||||
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
|
||||
x, y, width, 200, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Combobox::add_item(const char *data) {
|
||||
SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)data);
|
||||
if(SendMessage(hwnd, CB_GETCOUNT, 0, 0) == 1) { set_selection(0); }
|
||||
}
|
||||
|
||||
void Combobox::set_selection(int index) {
|
||||
SendMessage(hwnd, CB_SETCURSEL, index, 0);
|
||||
}
|
||||
|
||||
int Combobox::get_selection() {
|
||||
return SendMessage(hwnd, CB_GETCURSEL, 0, 0);
|
||||
}
|
||||
|
||||
void Combobox::reset() {
|
||||
SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
|
||||
}
|
||||
|
||||
/*****
|
||||
* Progressbar
|
||||
*****/
|
||||
|
||||
void Progressbar::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) {
|
||||
type = ControlType::Progressbar;
|
||||
hwnd = CreateWindow(PROGRESS_CLASS, "", WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
|
||||
SendMessage(hwnd, PBM_SETSTEP, MAKEWPARAM(1, 0), 0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Progressbar::set_progress(uint progress) {
|
||||
progress = minmax<0, 100>(progress);
|
||||
SendMessage(hwnd, PBM_SETPOS, (WPARAM)progress, 0);
|
||||
}
|
||||
|
||||
uint Progressbar::get_progress() {
|
||||
return minmax<0, 100>(SendMessage(hwnd, PBM_GETPOS, 0, 0));
|
||||
}
|
||||
|
||||
/*****
|
||||
* Slider
|
||||
*****/
|
||||
|
||||
void Slider::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, uint range) {
|
||||
type = ControlType::Slider;
|
||||
orientation = (style & Vertical) ? 1 : 0;
|
||||
if(range < 1)range = 1;
|
||||
|
||||
hwnd = CreateWindow(TRACKBAR_CLASS, "",
|
||||
WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_BOTH | (orientation == 0 ? TBS_HORZ : TBS_VERT),
|
||||
x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0);
|
||||
SendMessage(hwnd, TBM_SETRANGE, (WPARAM)true, (LPARAM)MAKELONG(0, range - 1));
|
||||
SendMessage(hwnd, TBM_SETPAGESIZE, 0, (LPARAM)(range >> 3));
|
||||
SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)0);
|
||||
r_owner.attach(*this);
|
||||
}
|
||||
|
||||
void Slider::set_position(uint position) {
|
||||
SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)position);
|
||||
}
|
||||
|
||||
uint Slider::get_position() {
|
||||
return SendMessage(hwnd, TBM_GETPOS, 0, 0);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,271 +0,0 @@
|
||||
namespace ControlType {
|
||||
enum {
|
||||
Invalid,
|
||||
MenuBar,
|
||||
MenuGroup,
|
||||
MenuItem,
|
||||
MenuCheckItem,
|
||||
MenuRadioItem,
|
||||
MenuSeparator,
|
||||
Panel,
|
||||
Container,
|
||||
Canvas,
|
||||
Frame,
|
||||
Label,
|
||||
Button,
|
||||
Checkbox,
|
||||
Radiobox,
|
||||
Editbox,
|
||||
Listbox,
|
||||
Combobox,
|
||||
Progressbar,
|
||||
Slider,
|
||||
};
|
||||
};
|
||||
|
||||
class Control { public:
|
||||
uint type;
|
||||
void move(uint x, uint y);
|
||||
void resize(uint width, uint height);
|
||||
|
||||
void focus();
|
||||
|
||||
virtual void show();
|
||||
virtual void hide();
|
||||
virtual void show(bool state);
|
||||
virtual bool visible();
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
void enable(bool state);
|
||||
bool enabled();
|
||||
|
||||
//private:
|
||||
Window *owner;
|
||||
HWND hwnd;
|
||||
uint id;
|
||||
|
||||
public:
|
||||
Control() : owner(0), hwnd(0), id(0), type(ControlType::Invalid) {}
|
||||
};
|
||||
|
||||
class ControlGroup { public:
|
||||
uint count() { return list.size(); }
|
||||
void add(Control &control) { list[list.size()] = &control; }
|
||||
void reset() { list.reset(); }
|
||||
ControlGroup &operator=(ControlGroup &source) { list = source.list; return *this; }
|
||||
Control &operator[](int index) { return *list[index]; }
|
||||
|
||||
//private:
|
||||
array<Control*> list;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
class MenuBar : public Control { public:
|
||||
void create(Window &owner);
|
||||
void finish();
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
void show(bool state);
|
||||
bool visible();
|
||||
|
||||
//private:
|
||||
HMENU group;
|
||||
};
|
||||
|
||||
class MenuGroup : public Control { public:
|
||||
void create(MenuBar &owner, const char *caption);
|
||||
void create(MenuGroup &owner, const char *caption);
|
||||
void finish();
|
||||
|
||||
//private:
|
||||
HMENU parent, group;
|
||||
char *caption;
|
||||
~MenuGroup() { safe_free(caption); }
|
||||
};
|
||||
|
||||
class MenuItem : public Control { public:
|
||||
void create(MenuGroup &owner, const char *caption);
|
||||
};
|
||||
|
||||
class MenuCheckItem : public Control { public:
|
||||
void create(MenuGroup &owner, const char *caption);
|
||||
void check();
|
||||
void uncheck();
|
||||
void check(bool state);
|
||||
bool checked();
|
||||
|
||||
//private:
|
||||
HMENU parent;
|
||||
};
|
||||
|
||||
class MenuRadioItem : public Control { public:
|
||||
void create(MenuGroup &owner, ControlGroup &list, const char *caption);
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
//private:
|
||||
HMENU parent;
|
||||
ControlGroup group;
|
||||
};
|
||||
|
||||
class MenuSeparator : public Control { public:
|
||||
void create(MenuGroup &owner);
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
class Panel : public Control { public:
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void attach(Window &window);
|
||||
void detach();
|
||||
|
||||
//private:
|
||||
Window *attached;
|
||||
Panel() : attached(0) {}
|
||||
};
|
||||
|
||||
class Container : public Control { public:
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void set_background_color(uint8 r, uint8 g, uint8 b);
|
||||
|
||||
//platform-dependent:
|
||||
HWND handle();
|
||||
|
||||
//private:
|
||||
HBRUSH background;
|
||||
Container();
|
||||
};
|
||||
|
||||
class Canvas : public Control { public:
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void redraw();
|
||||
|
||||
//private:
|
||||
BITMAPINFO bmi;
|
||||
uint32 *buffer;
|
||||
uint pitch, _w, _h;
|
||||
void blit();
|
||||
Canvas();
|
||||
~Canvas();
|
||||
};
|
||||
|
||||
class Frame : public Control { public:
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
};
|
||||
|
||||
class Label : public Control { public:
|
||||
enum { ideal_height = 16 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void set_text(const char *str, ...);
|
||||
};
|
||||
|
||||
class Button : public Control { public:
|
||||
enum { ideal_height = 21 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
};
|
||||
|
||||
class Checkbox : public Control { public:
|
||||
enum { ideal_height = 15 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void check();
|
||||
void uncheck();
|
||||
void check(bool state);
|
||||
bool checked();
|
||||
};
|
||||
|
||||
class Radiobox : public Control { public:
|
||||
enum { ideal_height = 15 };
|
||||
void create(Window &owner, ControlGroup &list, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
//private:
|
||||
ControlGroup group;
|
||||
};
|
||||
|
||||
class Editbox : public Control { public:
|
||||
enum { ideal_height = 21 };
|
||||
enum {
|
||||
Multiline = (1 << 1),
|
||||
Readonly = (1 << 2),
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = (1 << 3),
|
||||
HorizontalScrollNever = (1 << 4),
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = (1 << 5),
|
||||
VerticalScrollNever = (1 << 6),
|
||||
};
|
||||
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
|
||||
void set_text(const char *str, ...);
|
||||
uint get_text(char *str, uint length);
|
||||
|
||||
//private:
|
||||
bool multiline;
|
||||
bool readonly;
|
||||
bool vscroll;
|
||||
bool hscroll;
|
||||
};
|
||||
|
||||
class Listbox : public Control { public:
|
||||
enum {
|
||||
Header = (1 << 1),
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = (1 << 2),
|
||||
HorizontalScrollNever = (1 << 3),
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = (1 << 4),
|
||||
VerticalScrollNever = (1 << 5),
|
||||
};
|
||||
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *columns = "");
|
||||
void autosize_columns();
|
||||
void set_column_width(uint column, uint width);
|
||||
void add_item(const char *data, ...);
|
||||
void set_item(uint index, const char *data, ...);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
//private:
|
||||
bool header;
|
||||
uint column_count;
|
||||
};
|
||||
|
||||
class Combobox : public Control { public:
|
||||
enum { ideal_height = 21 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void add_item(const char *data);
|
||||
void set_selection(int index);
|
||||
int get_selection();
|
||||
void reset();
|
||||
};
|
||||
|
||||
class Progressbar : public Control { public:
|
||||
enum { ideal_height = 30 };
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height);
|
||||
void set_progress(uint progress);
|
||||
uint get_progress();
|
||||
};
|
||||
|
||||
class Slider : public Control { public:
|
||||
enum { ideal_height = 25 };
|
||||
enum Style {
|
||||
Horizontal = 0,
|
||||
Vertical = 1,
|
||||
};
|
||||
|
||||
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, uint range);
|
||||
void set_position(uint position);
|
||||
uint get_position();
|
||||
|
||||
//private:
|
||||
bool orientation;
|
||||
};
|
||||
@@ -1,290 +0,0 @@
|
||||
namespace libui {
|
||||
|
||||
long __stdcall libui_wndproc(HWND hwnd, uint msg, WPARAM wparam, LPARAM lparam) {
|
||||
Window *window = reinterpret_cast<Window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if(window) { return window->wndproc(hwnd, msg, wparam, lparam); }
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
long Window::wndproc(HWND hwnd, uint msg, WPARAM wparam, LPARAM lparam) {
|
||||
switch(msg) {
|
||||
|
||||
case WM_CLOSE: {
|
||||
if(message(Message::Close) == false) { return TRUE; }
|
||||
} break;
|
||||
|
||||
case WM_ENTERMENULOOP: {
|
||||
message(Message::Block);
|
||||
}
|
||||
|
||||
case WM_PAINT: {
|
||||
uint16 i = LOWORD(wparam);
|
||||
if(!i || !info.control[i])break;
|
||||
Control &control = *info.control[i];
|
||||
if(control.id != i)break; //this should never happen
|
||||
|
||||
switch(control.type) {
|
||||
|
||||
case ControlType::Canvas: {
|
||||
((Canvas&)control).redraw();
|
||||
} break;
|
||||
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_KEYDOWN: {
|
||||
message(Message::KeyDown, libui::translate_key(wparam));
|
||||
} break;
|
||||
|
||||
case WM_KEYUP: {
|
||||
message(Message::KeyUp, libui::translate_key(wparam));
|
||||
} break;
|
||||
|
||||
case WM_COMMAND: {
|
||||
uint16 i = LOWORD(wparam);
|
||||
if(!i || !info.control[i])break;
|
||||
Control &control = *info.control[i];
|
||||
if(control.id != i)break; //this should never happen
|
||||
|
||||
switch(control.type) {
|
||||
|
||||
//emit Message::Clicked message indirectly, through control.check()
|
||||
case ControlType::MenuCheckItem: {
|
||||
((MenuCheckItem&)control).check(!((MenuCheckItem&)control).checked()); //toggle checked status
|
||||
} break;
|
||||
|
||||
case ControlType::MenuRadioItem: {
|
||||
((MenuRadioItem&)control).check();
|
||||
} break;
|
||||
|
||||
case ControlType::Checkbox: {
|
||||
((Checkbox&)control).check(!((Checkbox&)control).checked()); //toggle checked status
|
||||
} break;
|
||||
|
||||
case ControlType::Radiobox: {
|
||||
((Radiobox&)control).check();
|
||||
} break;
|
||||
|
||||
//emit Message::Clicked message directly
|
||||
case ControlType::MenuItem:
|
||||
case ControlType::Button: {
|
||||
message(Message::Clicked, (uintptr_t)&control);
|
||||
} break;
|
||||
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
case WM_VSCROLL: {
|
||||
uint16 i = GetDlgCtrlID((HWND)lparam);
|
||||
if(!i || !info.control[i])break;
|
||||
Control &control = *info.control[i];
|
||||
if(control.id != i)break;
|
||||
|
||||
switch(control.type) {
|
||||
|
||||
case ControlType::Slider: {
|
||||
message(Message::Changed, (uintptr_t)&control);
|
||||
} break;
|
||||
|
||||
}
|
||||
} break;
|
||||
|
||||
case WM_NOTIFY: {
|
||||
uint16 i = (uint16)wparam;
|
||||
if(!i || !info.control[i])break;
|
||||
Control &control = *info.control[i];
|
||||
if(control.id != i)break;
|
||||
|
||||
switch(control.type) {
|
||||
|
||||
case ControlType::Listbox: {
|
||||
Listbox &listbox = ((Listbox&)control);
|
||||
if(((LPNMHDR)lparam)->code == LVN_ITEMCHANGED) {
|
||||
if(((LPNMLISTVIEW)lparam)->uChanged & LVIF_STATE) {
|
||||
if(ListView_GetItemState(listbox.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_FOCUSED)) {
|
||||
if(ListView_GetItemState(listbox.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_SELECTED)) {
|
||||
message(Message::Changed, (uintptr_t)&control);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(((LPNMHDR)lparam)->code == LVN_ITEMACTIVATE) {
|
||||
message(Message::DoubleClicked, (uintptr_t)&control);
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
void Window::attach(Control &control) {
|
||||
info.control[info.control_index] = &control;
|
||||
control.id = info.control_index++;
|
||||
control.owner = this;
|
||||
|
||||
//menu items will not have HWND, and do not require GWL_ID to be set
|
||||
if(control.hwnd) { SetWindowLong(control.hwnd, GWL_ID, control.id); }
|
||||
}
|
||||
|
||||
void Window::focus() {
|
||||
if(!visible()) { show(); }
|
||||
SetFocus(info.hwnd);
|
||||
}
|
||||
|
||||
bool Window::focused() {
|
||||
return (GetForegroundWindow() == info.hwnd);
|
||||
}
|
||||
|
||||
void Window::move(Control &control, uint x, uint y) {
|
||||
SetWindowPos(control.hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
||||
}
|
||||
|
||||
void Window::create(uint style, uint width, uint height, const char *caption) {
|
||||
info.center = bool(style & Center);
|
||||
|
||||
char classname[4096];
|
||||
sprintf(classname, "libui_class_%d", window_count++);
|
||||
WNDCLASS wc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||
wc.hInstance = GetModuleHandle(0);
|
||||
wc.lpfnWndProc = libui_wndproc;
|
||||
wc.lpszClassName = classname;
|
||||
wc.lpszMenuName = 0;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
RegisterClass(&wc);
|
||||
|
||||
RECT rc;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
|
||||
|
||||
info.hwnd = CreateWindowEx(0, classname, caption ? caption : "",
|
||||
WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
|
||||
rc.left, rc.top, width, height, 0, 0, GetModuleHandle(0), 0);
|
||||
info.hwnd_resize = CreateWindowEx(0, "libui_class", "",
|
||||
WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
|
||||
rc.left, rc.top, width, height, 0, 0, GetModuleHandle(0), 0);
|
||||
SetWindowLongPtr(info.hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
void Window::move(uint x, uint y) {
|
||||
RECT rc;
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
|
||||
if(x < rc.left) { x = rc.left; }
|
||||
if(y < rc.top ) { y = rc.top; }
|
||||
SetWindowPos(info.hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
||||
}
|
||||
|
||||
void Window::resize(uint width, uint height) {
|
||||
if(info.fullscreen == true) {
|
||||
info.width = GetSystemMetrics(SM_CXSCREEN);
|
||||
info.height = GetSystemMetrics(SM_CYSCREEN);
|
||||
SetWindowPos(info.hwnd, 0, 0, 0, info.width, info.height, SWP_NOZORDER);
|
||||
return;
|
||||
}
|
||||
|
||||
info.width = width;
|
||||
info.height = height;
|
||||
|
||||
//set requested window size to hidden window, calculate the difference between requested and actual client
|
||||
//size area, and then adjust width so that new width, height values will set requested client area size.
|
||||
//AdjustWindowRect() does not properly calculate the height of multi-line menus, and thusly is not used.
|
||||
SetWindowPos(info.hwnd_resize, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
|
||||
RECT rc;
|
||||
GetClientRect(info.hwnd_resize, &rc);
|
||||
width += width - (rc.right - rc.left);
|
||||
height += height - (rc.bottom - rc.top);
|
||||
|
||||
int x = (GetSystemMetrics(SM_CXSCREEN) - int(width)) / 2;
|
||||
int y = (GetSystemMetrics(SM_CYSCREEN) - int(height)) / 2;
|
||||
|
||||
//do not allow window to be placed offscreen, force to top-left if window is larger than screen size
|
||||
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
|
||||
if(x < rc.left) { x = rc.left; }
|
||||
if(y < rc.top) { y = rc.top; }
|
||||
|
||||
SetWindowPos(info.hwnd, 0, x, y, width, height, SWP_NOZORDER | (info.center == true ? 0 : SWP_NOMOVE));
|
||||
}
|
||||
|
||||
void Window::show() {
|
||||
ShowWindow(info.hwnd, SW_NORMAL);
|
||||
SetFocus(info.hwnd);
|
||||
}
|
||||
|
||||
void Window::hide() {
|
||||
ShowWindow(info.hwnd, SW_HIDE);
|
||||
}
|
||||
|
||||
void Window::show(bool state) {
|
||||
(state == true) ? show() : hide();
|
||||
}
|
||||
|
||||
bool Window::visible() {
|
||||
return GetWindowLong(info.hwnd, GWL_STYLE) & WS_VISIBLE;
|
||||
}
|
||||
|
||||
void Window::fullscreen() {
|
||||
if(info.fullscreen)return;
|
||||
info.fullscreen = true;
|
||||
SetWindowLong(info.hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
||||
resize(get_screen_width(), get_screen_height());
|
||||
}
|
||||
|
||||
void Window::unfullscreen() {
|
||||
if(!info.fullscreen)return;
|
||||
info.fullscreen = false;
|
||||
SetWindowLong(info.hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE);
|
||||
resize(info.width, info.height);
|
||||
}
|
||||
|
||||
void Window::fullscreen(bool state) {
|
||||
(state == true) ? fullscreen() : unfullscreen();
|
||||
}
|
||||
|
||||
bool Window::is_fullscreen() {
|
||||
return info.fullscreen;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void Window::set_text(const char *str, ...) {
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
string temp;
|
||||
vsprintf(temp, str, args);
|
||||
va_end(args);
|
||||
SetWindowText(info.hwnd, strptr(temp));
|
||||
}
|
||||
|
||||
void Window::set_background_color(uint8 r, uint8 g, uint8 b) {
|
||||
HBRUSH old_brush = info.background;
|
||||
info.background = (HBRUSH)CreateSolidBrush(RGB(r, g, b));
|
||||
SetClassLong(info.hwnd, GCL_HBRBACKGROUND, (LONG)info.background);
|
||||
InvalidateRect(info.hwnd, 0, TRUE);
|
||||
if(old_brush) { DeleteObject((HGDIOBJ)old_brush); }
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Window::Window() {
|
||||
info.fullscreen = false;
|
||||
info.background = 0;
|
||||
info.center = false;
|
||||
info.control_index = 1;
|
||||
}
|
||||
|
||||
//platform-dependent:
|
||||
|
||||
HWND Window::handle() {
|
||||
return info.hwnd;
|
||||
}
|
||||
|
||||
};
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
#include "miu.h"
|
||||
|
||||
namespace ns_miu {
|
||||
|
||||
/* Miu (singleton) */
|
||||
|
||||
void Miu::init() { p.init(); }
|
||||
void Miu::term() { p.term(); }
|
||||
bool Miu::run() { return p.run(); }
|
||||
bool Miu::pending() { return p.pending(); }
|
||||
bool Miu::file_load(Window *focus, char *filename, const char *filter, const char *path) { return p.file_load(focus, filename, filter, path); }
|
||||
bool Miu::file_save(Window *focus, char *filename, const char *filter, const char *path) { return p.file_save(focus, filename, filter, path); }
|
||||
uint Miu::screen_width() { return p.screen_width(); }
|
||||
uint Miu::screen_height() { return p.screen_height(); }
|
||||
Miu& Miu::handle() { static Miu miu; return miu; }
|
||||
Miu::Miu() : p(*new pMiu(*this)) {}
|
||||
Miu::~Miu() { delete &p; }
|
||||
Miu& miu() { return Miu::handle(); }
|
||||
|
||||
/* Widget */
|
||||
|
||||
void Widget::show(bool state) { p.show(state); }
|
||||
void Widget::hide() { p.hide(); }
|
||||
bool Widget::visible() { return p.visible(); }
|
||||
uintptr_t Widget::handle() { return p.handle(); }
|
||||
Widget::Widget() : p(*new pWidget(*this)) { type = WidgetType; }
|
||||
Widget::Widget(pWidget &p_) : p(p_) { type = WidgetType; }
|
||||
Widget::~Widget() { delete &p; }
|
||||
|
||||
/* Widget -> Window */
|
||||
|
||||
void Window::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
||||
void Window::close() { p.close(); }
|
||||
void Window::move(uint x, uint y) { p.move(x, y); }
|
||||
void Window::resize(uint width, uint height) { p.resize(width, height); }
|
||||
void Window::focus() { p.focus(); }
|
||||
bool Window::focused() { return p.focused(); }
|
||||
void Window::fullscreen() { p.fullscreen(); }
|
||||
void Window::unfullscreen() { p.unfullscreen(); }
|
||||
void Window::set_background_color(uint8 r, uint8 g, uint8 b) { p.set_background_color(r, g, b); }
|
||||
void Window::set_text(const char *text) { p.set_text(text); }
|
||||
void Window::attach(Window &window, uint x, uint y) { p.attach(window, x, y); }
|
||||
void Window::attach(MenuGroup &menugroup) { p.attach(menugroup); }
|
||||
void Window::attach(FormControl &formcontrol, uint x, uint y) { p.attach(formcontrol, x, y); }
|
||||
void Window::move(Window &window, uint x, uint y) { p.move(window, x, y); }
|
||||
void Window::move(FormControl &formcontrol, uint x, uint y) { p.move(formcontrol, x, y); }
|
||||
void Window::menu_show(bool state) { p.menu_show(state); }
|
||||
void Window::menu_hide() { p.menu_hide(); }
|
||||
bool Window::menu_visible() { return p.menu_visible(); }
|
||||
Window::Window() :
|
||||
base_from_member<pWindow&>(*new pWindow(*this)),
|
||||
Widget(base_from_member<pWindow&>::value),
|
||||
p(base_from_member<pWindow&>::value) { type = WindowType; }
|
||||
Window::Window(pWindow &p_) :
|
||||
base_from_member<pWindow&>(p_),
|
||||
Widget(base_from_member<pWindow&>::value),
|
||||
p(base_from_member<pWindow&>::value) { type = WindowType; }
|
||||
|
||||
/* Widget -> MenuControl */
|
||||
|
||||
void MenuControl::enable(bool state) { p.enable(state); }
|
||||
void MenuControl::disable() { p.disable(); }
|
||||
bool MenuControl::enabled() { return p.enabled(); }
|
||||
MenuControl::MenuControl() :
|
||||
base_from_member<pMenuControl&>(*new pMenuControl(*this)),
|
||||
Widget(base_from_member<pMenuControl&>::value),
|
||||
p(base_from_member<pMenuControl&>::value) { type = MenuControlType; }
|
||||
MenuControl::MenuControl(pMenuControl &p_) :
|
||||
base_from_member<pMenuControl&>(p_),
|
||||
Widget(base_from_member<pMenuControl&>::value),
|
||||
p(base_from_member<pMenuControl&>::value) { type = MenuControlType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuGroup */
|
||||
|
||||
MenuGroup& MenuGroup::create(const char *text) { p.create(text); return *this; }
|
||||
void MenuGroup::attach(MenuControl &menucontrol) { p.attach(menucontrol); }
|
||||
MenuGroup::MenuGroup() :
|
||||
base_from_member<pMenuGroup&>(*new pMenuGroup(*this)),
|
||||
MenuControl(base_from_member<pMenuGroup&>::value),
|
||||
p(base_from_member<pMenuGroup&>::value) { type = MenuGroupType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuItem */
|
||||
|
||||
MenuItem& MenuItem::create(const char *text) { p.create(text); return *this; }
|
||||
MenuItem::MenuItem() :
|
||||
base_from_member<pMenuItem&>(*new pMenuItem(*this)),
|
||||
MenuControl(base_from_member<pMenuItem&>::value),
|
||||
p(base_from_member<pMenuItem&>::value) { type = MenuItemType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuCheckItem */
|
||||
|
||||
MenuCheckItem& MenuCheckItem::create(const char *text) { p.create(text); return *this; }
|
||||
void MenuCheckItem::check(bool state) { state ? p.check() : p.uncheck(); }
|
||||
void MenuCheckItem::uncheck() { p.uncheck(); }
|
||||
bool MenuCheckItem::checked() { return p.checked(); }
|
||||
MenuCheckItem::MenuCheckItem() :
|
||||
base_from_member<pMenuCheckItem&>(*new pMenuCheckItem(*this)),
|
||||
MenuControl(base_from_member<pMenuCheckItem&>::value),
|
||||
p(base_from_member<pMenuCheckItem&>::value) { type = MenuCheckItemType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuRadioItem */
|
||||
|
||||
MenuRadioItem& MenuRadioItem::create(MenuRadioItemGroup &group, const char *text) { p.create(group, text); return *this; }
|
||||
void MenuRadioItem::check() { p.check(); }
|
||||
bool MenuRadioItem::checked() { return p.checked(); }
|
||||
MenuRadioItem::MenuRadioItem() :
|
||||
base_from_member<pMenuRadioItem&>(*new pMenuRadioItem(*this)),
|
||||
MenuControl(base_from_member<pMenuRadioItem&>::value),
|
||||
p(base_from_member<pMenuRadioItem&>::value) { type = MenuRadioItemType; }
|
||||
|
||||
/* Widget -> MenuControl -> MenuSeparator */
|
||||
|
||||
MenuSeparator& MenuSeparator::create() { p.create(); return *this; }
|
||||
MenuSeparator::MenuSeparator() :
|
||||
base_from_member<pMenuSeparator&>(*new pMenuSeparator(*this)),
|
||||
MenuControl(base_from_member<pMenuSeparator&>::value),
|
||||
p(base_from_member<pMenuSeparator&>::value) { type = MenuSeparatorType; }
|
||||
|
||||
/* Widget -> FormControl */
|
||||
|
||||
void FormControl::resize(uint width, uint height) { p.resize(width, height); }
|
||||
void FormControl::focus() { p.focus(); }
|
||||
bool FormControl::focused() { return p.focused(); }
|
||||
void FormControl::enable(bool state) { p.enable(state); }
|
||||
void FormControl::disable() { p.disable(); }
|
||||
bool FormControl::enabled() { return p.enabled(); }
|
||||
FormControl::FormControl() :
|
||||
base_from_member<pFormControl&>(*new pFormControl(*this)),
|
||||
Widget(base_from_member<pFormControl&>::value),
|
||||
p(base_from_member<pFormControl&>::value) { type = FormControlType; }
|
||||
FormControl::FormControl(pFormControl &p_) :
|
||||
base_from_member<pFormControl&>(p_),
|
||||
Widget(base_from_member<pFormControl&>::value),
|
||||
p(base_from_member<pFormControl&>::value) { type = FormControlType; }
|
||||
|
||||
/* Widget -> FormControl -> Frame */
|
||||
|
||||
void Frame::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
||||
void Frame::set_text(const char *text) { p.set_text(text); }
|
||||
Frame::Frame() :
|
||||
base_from_member<pFrame&>(*new pFrame(*this)),
|
||||
FormControl(base_from_member<pFrame&>::value),
|
||||
p(base_from_member<pFrame&>::value) { type = FrameType; }
|
||||
|
||||
/* Widget -> FormControl -> Canvas */
|
||||
|
||||
void Canvas::create(uint style, uint width, uint height) { p.create(style, width, height); }
|
||||
void Canvas::redraw() { p.redraw(); }
|
||||
uint32* Canvas::buffer() { return p.buffer(); }
|
||||
Canvas::Canvas() :
|
||||
base_from_member<pCanvas&>(*new pCanvas(*this)),
|
||||
FormControl(base_from_member<pCanvas&>::value),
|
||||
p(base_from_member<pCanvas&>::value) { type = CanvasType; }
|
||||
|
||||
/* Widget -> FormControl -> Label */
|
||||
|
||||
void Label::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
||||
void Label::set_text(const char *text) { p.set_text(text); }
|
||||
Label::Label() :
|
||||
base_from_member<pLabel&>(*new pLabel(*this)),
|
||||
FormControl(base_from_member<pLabel&>::value),
|
||||
p(base_from_member<pLabel&>::value) { type = LabelType; }
|
||||
|
||||
/* Widget -> FormControl -> Button */
|
||||
|
||||
void Button::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
||||
void Button::set_text(const char *text) { p.set_text(text); }
|
||||
Button::Button() :
|
||||
base_from_member<pButton&>(*new pButton(*this)),
|
||||
FormControl(base_from_member<pButton&>::value),
|
||||
p(base_from_member<pButton&>::value) { type = ButtonType; }
|
||||
|
||||
/* Widget -> FormControl -> Checkbox */
|
||||
|
||||
void Checkbox::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
||||
void Checkbox::set_text(const char *text) { p.set_text(text); }
|
||||
void Checkbox::check(bool state) { state ? p.check() : p.uncheck(); }
|
||||
void Checkbox::uncheck() { p.uncheck(); }
|
||||
bool Checkbox::checked() { return p.checked(); }
|
||||
Checkbox::Checkbox() :
|
||||
base_from_member<pCheckbox&>(*new pCheckbox(*this)),
|
||||
FormControl(base_from_member<pCheckbox&>::value),
|
||||
p(base_from_member<pCheckbox&>::value) { type = CheckboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Radiobox */
|
||||
|
||||
void Radiobox::create(RadioboxGroup &group, uint style, uint width, uint height, const char *text) { p.create(group, style, width, height, text); }
|
||||
void Radiobox::set_text(const char *text) { p.set_text(text); }
|
||||
void Radiobox::check() { p.check(); }
|
||||
bool Radiobox::checked() { return p.checked(); }
|
||||
Radiobox::Radiobox() :
|
||||
base_from_member<pRadiobox&>(*new pRadiobox(*this)),
|
||||
FormControl(base_from_member<pRadiobox&>::value),
|
||||
p(base_from_member<pRadiobox&>::value) { type = RadioboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Editbox */
|
||||
|
||||
void Editbox::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
||||
uint Editbox::get_text(char *text, uint length) { return p.get_text(text, length); }
|
||||
void Editbox::set_text(const char *text) { p.set_text(text); }
|
||||
Editbox::Editbox() :
|
||||
base_from_member<pEditbox&>(*new pEditbox(*this)),
|
||||
FormControl(base_from_member<pEditbox&>::value),
|
||||
p(base_from_member<pEditbox&>::value) { type = EditboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Listbox */
|
||||
|
||||
void Listbox::create(uint style, uint width, uint height, const char *columns, const char *text) { p.create(style, width, height, columns, text); }
|
||||
void Listbox::autosize_columns() { p.autosize_columns(); }
|
||||
void Listbox::set_column_width(uint column, uint width) { p.set_column_width(column, width); }
|
||||
void Listbox::add_item(const char *text) { p.add_item(text); }
|
||||
void Listbox::set_item(uint index, const char *text) { p.set_item(index, text); }
|
||||
int Listbox::get_selection() { return p.get_selection(); }
|
||||
void Listbox::set_selection(int index) { p.set_selection(index); }
|
||||
void Listbox::reset() { p.reset(); }
|
||||
Listbox::Listbox() :
|
||||
base_from_member<pListbox&>(*new pListbox(*this)),
|
||||
FormControl(base_from_member<pListbox&>::value),
|
||||
p(base_from_member<pListbox&>::value) { type = ListboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Combobox */
|
||||
|
||||
void Combobox::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
||||
void Combobox::add_item(const char *text) { p.add_item(text); }
|
||||
int Combobox::get_selection() { return p.get_selection(); }
|
||||
void Combobox::set_selection(int index) { p.set_selection(index); }
|
||||
void Combobox::reset() { p.reset(); }
|
||||
Combobox::Combobox() :
|
||||
base_from_member<pCombobox&>(*new pCombobox(*this)),
|
||||
FormControl(base_from_member<pCombobox&>::value),
|
||||
p(base_from_member<pCombobox&>::value) { type = ComboboxType; }
|
||||
|
||||
/* Widget -> FormControl -> Progressbar */
|
||||
|
||||
void Progressbar::create(uint style, uint width, uint height) { p.create(style, width, height); }
|
||||
uint Progressbar::get_progress() { return p.get_progress(); }
|
||||
void Progressbar::set_progress(uint progress) { p.set_progress(progress); }
|
||||
Progressbar::Progressbar() :
|
||||
base_from_member<pProgressbar&>(*new pProgressbar(*this)),
|
||||
FormControl(base_from_member<pProgressbar&>::value),
|
||||
p(base_from_member<pProgressbar&>::value) { type = ProgressbarType; }
|
||||
|
||||
/* Widget -> FormControl -> Slider */
|
||||
|
||||
void Slider::create(uint style, uint width, uint height, uint length) { p.create(style, width, height, length); }
|
||||
uint Slider::get_position() { return p.get_position(); }
|
||||
void Slider::set_position(uint position) { p.set_position(position); }
|
||||
Slider::Slider() :
|
||||
base_from_member<pSlider&>(*new pSlider(*this)),
|
||||
FormControl(base_from_member<pSlider&>::value),
|
||||
p(base_from_member<pSlider&>::value) { type = SliderType; }
|
||||
|
||||
} //namespace ns_miu
|
||||
@@ -0,0 +1,25 @@
|
||||
void miu_pbutton_tick(pButton *p) {
|
||||
if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pButton::create(uint style, uint width, uint height, const char *text) {
|
||||
button = gtk_button_new_with_label(text ? text : "");
|
||||
gtk_widget_set_size_request(button, width, height);
|
||||
gtk_widget_show(button);
|
||||
g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(miu_pbutton_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pButton::set_text(const char *text) {
|
||||
if(!button) return;
|
||||
gtk_button_set_label(GTK_BUTTON(button), text ? text : "");
|
||||
}
|
||||
|
||||
pButton::pButton(Button &self_) : pFormControl(self_), self(self_) {
|
||||
button = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pButton::gtk_handle() {
|
||||
return button;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class pButton : public pFormControl {
|
||||
public:
|
||||
Button &self;
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pButton(Button&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *button;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
void miu_pcanvas_expose(pCanvas *p) {
|
||||
uint32 *f = p->fbuffer;
|
||||
uint32 *r = p->rbuffer;
|
||||
for(uint y = p->canvas->allocation.height; y; y--) {
|
||||
for(uint x = p->canvas->allocation.width; x; x--) {
|
||||
uint32 p = *f++;
|
||||
*r++ = ((p << 16) & 0xff0000) + (p & 0x00ff00) + ((p >> 16) & 0x0000ff);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_draw_rgb_32_image(p->canvas->window,
|
||||
p->canvas->style->fg_gc[GTK_WIDGET_STATE(p->canvas)],
|
||||
0, 0, p->canvas->allocation.width, p->canvas->allocation.height,
|
||||
GDK_RGB_DITHER_NONE, (guchar*)p->rbuffer, p->bpitch);
|
||||
}
|
||||
|
||||
void pCanvas::create(uint style, uint width, uint height) {
|
||||
canvas = gtk_drawing_area_new();
|
||||
resize(width, height);
|
||||
GdkColor color;
|
||||
color.pixel = color.red = color.green = color.blue = 0;
|
||||
gtk_widget_modify_bg(canvas, GTK_STATE_NORMAL, &color);
|
||||
gtk_widget_show(canvas);
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(canvas), "expose_event", G_CALLBACK(miu_pcanvas_expose), (gpointer)this);
|
||||
}
|
||||
|
||||
void pCanvas::redraw() {
|
||||
if(!canvas || !canvas->window) return;
|
||||
|
||||
GdkRectangle rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = canvas->allocation.width;
|
||||
rect.height = canvas->allocation.height;
|
||||
gdk_window_invalidate_rect(canvas->window, &rect, true);
|
||||
}
|
||||
|
||||
uint32* pCanvas::buffer() {
|
||||
return fbuffer;
|
||||
}
|
||||
|
||||
pCanvas::pCanvas(Canvas &self_) : pFormControl(self_), self(self_) {
|
||||
canvas = 0;
|
||||
fbuffer = 0;
|
||||
rbuffer = 0;
|
||||
bpitch = 0;
|
||||
}
|
||||
|
||||
pCanvas::~pCanvas() {
|
||||
safe_free(fbuffer);
|
||||
safe_free(rbuffer);
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
void pCanvas::resize(uint width, uint height) {
|
||||
safe_free(fbuffer);
|
||||
safe_free(rbuffer);
|
||||
|
||||
bpitch = width * sizeof(uint32);
|
||||
fbuffer = (uint32*)malloc(bpitch * height);
|
||||
rbuffer = (uint32*)malloc(bpitch * height);
|
||||
memset(fbuffer, 0, bpitch * height);
|
||||
memset(rbuffer, 0, bpitch * height);
|
||||
|
||||
pFormControl::resize(width, height);
|
||||
}
|
||||
|
||||
GtkWidget* pCanvas::gtk_handle() {
|
||||
return canvas;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class pCanvas : public pFormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height);
|
||||
void redraw();
|
||||
uint32* buffer();
|
||||
|
||||
Canvas &self;
|
||||
pCanvas(Canvas&);
|
||||
~pCanvas();
|
||||
|
||||
/* internal */
|
||||
GtkWidget *canvas;
|
||||
//GTK+ RGB drawing function draws in xBGR format, so two buffers are needed ...
|
||||
uint32 *fbuffer; //one for the xRGB image
|
||||
uint32 *rbuffer; //one for the xBGR image
|
||||
uint bpitch;
|
||||
void resize(uint width, uint height);
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
void miu_pcheckbox_tick(pCheckbox *p) {
|
||||
if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, p->checked(), &p->self));
|
||||
}
|
||||
|
||||
void pCheckbox::create(uint style, uint width, uint height, const char *text) {
|
||||
checkbox = gtk_check_button_new_with_label(text ? text : "");
|
||||
gtk_widget_set_size_request(checkbox, width, height);
|
||||
gtk_widget_show(checkbox);
|
||||
g_signal_connect_swapped(G_OBJECT(checkbox), "toggled", G_CALLBACK(miu_pcheckbox_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pCheckbox::set_text(const char *text) {
|
||||
if(!checkbox) return;
|
||||
gtk_button_set_label(GTK_BUTTON(checkbox), text ? text : "");
|
||||
}
|
||||
|
||||
void pCheckbox::check(bool state) {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), state ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void pCheckbox::uncheck() {
|
||||
check(false);
|
||||
}
|
||||
|
||||
bool pCheckbox::checked() {
|
||||
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox));
|
||||
}
|
||||
|
||||
pCheckbox::pCheckbox(Checkbox &self_) : pFormControl(self_), self(self_) {
|
||||
checkbox = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pCheckbox::gtk_handle() {
|
||||
return checkbox;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class pCheckbox : public pFormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check(bool state = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
Checkbox &self;
|
||||
pCheckbox(Checkbox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *checkbox;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
void miu_pcombobox_change(pCombobox *p) {
|
||||
if(p->self.on_change) p->self.on_change(Event(Event::Change, p->get_selection(), &p->self));
|
||||
}
|
||||
|
||||
void pCombobox::create(uint style, uint width, uint height, const char *text) {
|
||||
combobox = gtk_combo_box_new_text();
|
||||
gtk_widget_set_size_request(combobox, width, height);
|
||||
gtk_widget_show(combobox);
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(combobox), "changed", G_CALLBACK(miu_pcombobox_change), (gpointer)this);
|
||||
}
|
||||
|
||||
void pCombobox::add_item(const char *text) {
|
||||
if(!combobox) return;
|
||||
gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), text ? text : "?");
|
||||
if(counter++ == 0) set_selection(0);
|
||||
}
|
||||
|
||||
int pCombobox::get_selection() {
|
||||
return gtk_combo_box_get_active(GTK_COMBO_BOX(combobox));
|
||||
}
|
||||
|
||||
void pCombobox::set_selection(int index) {
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), index);
|
||||
}
|
||||
|
||||
void pCombobox::reset() {
|
||||
if(counter == 0) return;
|
||||
for(int i = counter - 1; i >= 0; i--) {
|
||||
gtk_combo_box_remove_text(GTK_COMBO_BOX(combobox), i);
|
||||
}
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
pCombobox::pCombobox(Combobox &self_) : pFormControl(self_), self(self_) {
|
||||
combobox = 0;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pCombobox::gtk_handle() {
|
||||
return combobox;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
class pCombobox : public pFormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void add_item(const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
Combobox &self;
|
||||
pCombobox(Combobox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *combobox;
|
||||
uint counter;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "miu.gtk.h"
|
||||
#include "../miu.cpp"
|
||||
|
||||
namespace ns_miu {
|
||||
|
||||
#include "miu.gtk.keymap.cpp"
|
||||
#include "miu.gtk.widget.cpp"
|
||||
#include "miu.gtk.window.cpp"
|
||||
#include "miu.gtk.menucontrol.cpp"
|
||||
#include "miu.gtk.menugroup.cpp"
|
||||
#include "miu.gtk.menuitem.cpp"
|
||||
#include "miu.gtk.menucheckitem.cpp"
|
||||
#include "miu.gtk.menuradioitem.cpp"
|
||||
#include "miu.gtk.menuseparator.cpp"
|
||||
#include "miu.gtk.formcontrol.cpp"
|
||||
#include "miu.gtk.frame.cpp"
|
||||
#include "miu.gtk.canvas.cpp"
|
||||
#include "miu.gtk.label.cpp"
|
||||
#include "miu.gtk.button.cpp"
|
||||
#include "miu.gtk.checkbox.cpp"
|
||||
#include "miu.gtk.radiobox.cpp"
|
||||
#include "miu.gtk.editbox.cpp"
|
||||
#include "miu.gtk.listbox.cpp"
|
||||
#include "miu.gtk.combobox.cpp"
|
||||
#include "miu.gtk.progressbar.cpp"
|
||||
#include "miu.gtk.slider.cpp"
|
||||
|
||||
void pMiu::init() {
|
||||
//simulate passing argc, argv to gtk_init()
|
||||
int argc = 1;
|
||||
char **argv;
|
||||
argv = (char**)malloc(1 * sizeof(char*));
|
||||
argv[0] = (char*)malloc(64 * sizeof(char));
|
||||
strcpy(argv[0], "./miu");
|
||||
gtk_init(&argc, &argv);
|
||||
safe_free(argv[0]);
|
||||
safe_free(argv);
|
||||
}
|
||||
|
||||
void pMiu::term() {
|
||||
}
|
||||
|
||||
bool pMiu::run() {
|
||||
gtk_main_iteration_do(false);
|
||||
return pending();
|
||||
}
|
||||
|
||||
bool pMiu::pending() {
|
||||
return gtk_events_pending();
|
||||
}
|
||||
|
||||
bool pMiu::file_load(Window *focus, char *filename, const char *filter, const char *path) {
|
||||
if(!filename) return false;
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Load File",
|
||||
focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0);
|
||||
|
||||
if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
strcpy(filename, fn);
|
||||
g_free(fn);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return strcmp(filename, ""); //return true if filename exists
|
||||
}
|
||||
|
||||
bool pMiu::file_save(Window *focus, char *filename, const char *filter, const char *path) {
|
||||
if(!filename) return false;
|
||||
strcpy(filename, "");
|
||||
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new("Save File",
|
||||
focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
||||
(const gchar*)0);
|
||||
|
||||
if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
|
||||
|
||||
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
strcpy(filename, fn);
|
||||
g_free(fn);
|
||||
}
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
return strcmp(filename, ""); //return true if filename exists
|
||||
}
|
||||
|
||||
uint pMiu::screen_width() {
|
||||
return gdk_screen_width();
|
||||
}
|
||||
|
||||
uint pMiu::screen_height() {
|
||||
return gdk_screen_height();
|
||||
}
|
||||
|
||||
pMiu& pMiu::handle() {
|
||||
return miu().p;
|
||||
}
|
||||
|
||||
pMiu::pMiu(Miu &self_) : self(self_) {
|
||||
}
|
||||
|
||||
pMiu& pmiu() {
|
||||
return pMiu::handle();
|
||||
}
|
||||
|
||||
} //namespace ns_miu
|
||||
@@ -0,0 +1,62 @@
|
||||
void pEditbox::create(uint style, uint width, uint height, const char *text) {
|
||||
multiline = bool(style & Editbox::Multiline);
|
||||
|
||||
if(multiline == false) {
|
||||
editbox = gtk_entry_new();
|
||||
if(style & Editbox::Readonly) { gtk_entry_set_editable(GTK_ENTRY(editbox), false); }
|
||||
gtk_entry_set_text(GTK_ENTRY(editbox), text ? text : "");
|
||||
gtk_widget_set_size_request(editbox, width, height);
|
||||
gtk_widget_show(editbox);
|
||||
} else {
|
||||
GtkPolicyType hscroll = (style & Editbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Editbox::HorizontalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
GtkPolicyType vscroll = (style & Editbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Editbox::VerticalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
scrollbox = gtk_scrolled_window_new(0, 0);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
||||
gtk_widget_set_size_request(scrollbox, width, height);
|
||||
editbox = gtk_text_view_new();
|
||||
gtk_container_add(GTK_CONTAINER(scrollbox), editbox);
|
||||
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(editbox));
|
||||
if(style & Editbox::Readonly) { gtk_text_view_set_editable(GTK_TEXT_VIEW(editbox), false); }
|
||||
gtk_text_buffer_set_text(buffer, text ? text : "", -1);
|
||||
gtk_widget_show(editbox);
|
||||
gtk_widget_show(scrollbox);
|
||||
}
|
||||
}
|
||||
|
||||
void pEditbox::set_text(const char *text) {
|
||||
if(multiline == false) {
|
||||
gtk_entry_set_text(GTK_ENTRY(editbox), text);
|
||||
} else {
|
||||
gtk_text_buffer_set_text(buffer, text, -1);
|
||||
}
|
||||
}
|
||||
|
||||
uint pEditbox::get_text(char *text, uint length) {
|
||||
if(multiline == false) {
|
||||
const char *temp = gtk_entry_get_text(GTK_ENTRY(editbox));
|
||||
return strlcpy(text, temp ? temp : "", length);
|
||||
} else {
|
||||
GtkTextIter start, end;
|
||||
gtk_text_buffer_get_start_iter(buffer, &start);
|
||||
gtk_text_buffer_get_end_iter(buffer, &end);
|
||||
return strlcpy(text, gtk_text_buffer_get_text(buffer, &start, &end, true), length);
|
||||
}
|
||||
}
|
||||
|
||||
pEditbox::pEditbox(Editbox &self_) : pFormControl(self_), self(self_) {
|
||||
scrollbox = 0;
|
||||
editbox = 0;
|
||||
buffer = 0;
|
||||
multiline = false;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pEditbox::gtk_handle() {
|
||||
return multiline ? scrollbox : editbox;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
class pEditbox : public pFormControl {
|
||||
public:
|
||||
Editbox &self;
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
uint get_text(char *text, uint length = -1U);
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pEditbox(Editbox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *scrollbox;
|
||||
GtkWidget *editbox;
|
||||
GtkTextBuffer *buffer;
|
||||
bool multiline;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
void pFormControl::resize(uint width, uint height) {
|
||||
gtk_widget_set_size_request(gtk_handle(), width, height);
|
||||
}
|
||||
|
||||
void pFormControl::focus() {
|
||||
gtk_widget_grab_focus(gtk_handle());
|
||||
}
|
||||
|
||||
bool pFormControl::focused() {
|
||||
return GTK_WIDGET_HAS_FOCUS(gtk_handle());
|
||||
}
|
||||
|
||||
void pFormControl::enable(bool state) {
|
||||
gtk_widget_set_sensitive(gtk_handle(), state);
|
||||
}
|
||||
|
||||
void pFormControl::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pFormControl::enabled() {
|
||||
return GTK_WIDGET_SENSITIVE(gtk_handle());
|
||||
}
|
||||
|
||||
pFormControl::pFormControl(FormControl &self_) : pWidget(self_), self(self_) {
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pFormControl::gtk_handle() {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class pFormControl : public pWidget {
|
||||
public:
|
||||
virtual void resize(uint width, uint height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
FormControl &self;
|
||||
pFormControl(FormControl&);
|
||||
|
||||
/* internal */
|
||||
virtual GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
void pFrame::create(uint style, uint width, uint height, const char *text) {
|
||||
frame = gtk_frame_new(text ? text : "");
|
||||
gtk_widget_set_size_request(frame, width, height);
|
||||
gtk_widget_show(frame);
|
||||
}
|
||||
|
||||
void pFrame::set_text(const char *text) {
|
||||
gtk_frame_set_label(GTK_FRAME(frame), text ? text : "");
|
||||
}
|
||||
|
||||
pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) {
|
||||
frame = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pFrame::gtk_handle() {
|
||||
return frame;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class pFrame : public pFormControl {
|
||||
public:
|
||||
Frame &self;
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pFrame(Frame&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *frame;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef MIU_GTK_H
|
||||
#define MIU_GTK_H
|
||||
|
||||
#include "../miu.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
namespace ns_miu {
|
||||
|
||||
#include "miu.gtk.widget.h"
|
||||
#include "miu.gtk.window.h"
|
||||
#include "miu.gtk.menucontrol.h"
|
||||
#include "miu.gtk.menugroup.h"
|
||||
#include "miu.gtk.menuitem.h"
|
||||
#include "miu.gtk.menucheckitem.h"
|
||||
#include "miu.gtk.menuradioitem.h"
|
||||
#include "miu.gtk.menuseparator.h"
|
||||
#include "miu.gtk.formcontrol.h"
|
||||
#include "miu.gtk.frame.h"
|
||||
#include "miu.gtk.canvas.h"
|
||||
#include "miu.gtk.label.h"
|
||||
#include "miu.gtk.button.h"
|
||||
#include "miu.gtk.checkbox.h"
|
||||
#include "miu.gtk.radiobox.h"
|
||||
#include "miu.gtk.editbox.h"
|
||||
#include "miu.gtk.listbox.h"
|
||||
#include "miu.gtk.combobox.h"
|
||||
#include "miu.gtk.progressbar.h"
|
||||
#include "miu.gtk.slider.h"
|
||||
|
||||
class pMiu {
|
||||
public:
|
||||
Miu &self;
|
||||
void init();
|
||||
void term();
|
||||
bool run();
|
||||
bool pending();
|
||||
|
||||
bool file_load(Window *focus, char *filename, const char *filter, const char *path);
|
||||
bool file_save(Window *focus, char *filename, const char *filter, const char *path);
|
||||
|
||||
uint screen_width();
|
||||
uint screen_height();
|
||||
|
||||
static pMiu& handle();
|
||||
pMiu(Miu&);
|
||||
|
||||
/* internal */
|
||||
uint16 translate_key(uint key);
|
||||
};
|
||||
|
||||
pMiu& pmiu();
|
||||
|
||||
} //namespace ns_miu
|
||||
|
||||
#endif //ifndef MIU_GTK_H
|
||||
@@ -0,0 +1,188 @@
|
||||
uint16 pMiu::translate_key(uint key) {
|
||||
switch(key) {
|
||||
case GDK_Escape: return keymap::esc;
|
||||
|
||||
case GDK_F1: return keymap::f1;
|
||||
case GDK_F2: return keymap::f2;
|
||||
case GDK_F3: return keymap::f3;
|
||||
case GDK_F4: return keymap::f4;
|
||||
case GDK_F5: return keymap::f5;
|
||||
case GDK_F6: return keymap::f6;
|
||||
case GDK_F7: return keymap::f7;
|
||||
case GDK_F8: return keymap::f8;
|
||||
case GDK_F9: return keymap::f9;
|
||||
case GDK_F10: return keymap::f10;
|
||||
case GDK_F11: return keymap::f11;
|
||||
case GDK_F12: return keymap::f12;
|
||||
|
||||
case GDK_Print: return keymap::print_screen;
|
||||
case GDK_Sys_Req: return keymap::sys_req;
|
||||
case GDK_Scroll_Lock: return keymap::scroll_lock;
|
||||
case GDK_Pause: return keymap::pause;
|
||||
case GDK_Break: return keymap::brk;
|
||||
|
||||
case GDK_grave: return keymap::grave;
|
||||
case GDK_asciitilde: return keymap::tilde;
|
||||
|
||||
case GDK_1: return keymap::num_1;
|
||||
case GDK_2: return keymap::num_2;
|
||||
case GDK_3: return keymap::num_3;
|
||||
case GDK_4: return keymap::num_4;
|
||||
case GDK_5: return keymap::num_5;
|
||||
case GDK_6: return keymap::num_6;
|
||||
case GDK_7: return keymap::num_7;
|
||||
case GDK_8: return keymap::num_8;
|
||||
case GDK_9: return keymap::num_9;
|
||||
case GDK_0: return keymap::num_0;
|
||||
|
||||
case GDK_exclam: return keymap::exclamation;
|
||||
case GDK_at: return keymap::at;
|
||||
case GDK_numbersign: return keymap::pound;
|
||||
case GDK_dollar: return keymap::dollar;
|
||||
case GDK_percent: return keymap::percent;
|
||||
case GDK_asciicircum: return keymap::power;
|
||||
case GDK_ampersand: return keymap::ampersand;
|
||||
case GDK_asterisk: return keymap::asterisk;
|
||||
case GDK_parenleft: return keymap::lparenthesis;
|
||||
case GDK_parenright: return keymap::rparenthesis;
|
||||
|
||||
case GDK_minus: return keymap::minus;
|
||||
case GDK_underscore: return keymap::underscore;
|
||||
case GDK_equal: return keymap::equal;
|
||||
case GDK_plus: return keymap::plus;
|
||||
case GDK_BackSpace: return keymap::backspace;
|
||||
|
||||
case GDK_Insert: return keymap::ins;
|
||||
case GDK_Delete: return keymap::del;
|
||||
case GDK_Home: return keymap::home;
|
||||
case GDK_End: return keymap::end;
|
||||
case GDK_Page_Up: return keymap::page_up;
|
||||
case GDK_Page_Down: return keymap::page_down;
|
||||
|
||||
case GDK_a: return keymap::a;
|
||||
case GDK_b: return keymap::b;
|
||||
case GDK_c: return keymap::c;
|
||||
case GDK_d: return keymap::d;
|
||||
case GDK_e: return keymap::e;
|
||||
case GDK_f: return keymap::f;
|
||||
case GDK_g: return keymap::g;
|
||||
case GDK_h: return keymap::h;
|
||||
case GDK_i: return keymap::i;
|
||||
case GDK_j: return keymap::j;
|
||||
case GDK_k: return keymap::k;
|
||||
case GDK_l: return keymap::l;
|
||||
case GDK_m: return keymap::m;
|
||||
case GDK_n: return keymap::n;
|
||||
case GDK_o: return keymap::o;
|
||||
case GDK_p: return keymap::p;
|
||||
case GDK_q: return keymap::q;
|
||||
case GDK_r: return keymap::r;
|
||||
case GDK_s: return keymap::s;
|
||||
case GDK_t: return keymap::t;
|
||||
case GDK_u: return keymap::u;
|
||||
case GDK_v: return keymap::v;
|
||||
case GDK_w: return keymap::w;
|
||||
case GDK_x: return keymap::x;
|
||||
case GDK_y: return keymap::y;
|
||||
case GDK_z: return keymap::z;
|
||||
|
||||
case GDK_A: return keymap::A;
|
||||
case GDK_B: return keymap::B;
|
||||
case GDK_C: return keymap::C;
|
||||
case GDK_D: return keymap::D;
|
||||
case GDK_E: return keymap::E;
|
||||
case GDK_F: return keymap::F;
|
||||
case GDK_G: return keymap::G;
|
||||
case GDK_H: return keymap::H;
|
||||
case GDK_I: return keymap::I;
|
||||
case GDK_J: return keymap::J;
|
||||
case GDK_K: return keymap::K;
|
||||
case GDK_L: return keymap::L;
|
||||
case GDK_M: return keymap::M;
|
||||
case GDK_N: return keymap::N;
|
||||
case GDK_O: return keymap::O;
|
||||
case GDK_P: return keymap::P;
|
||||
case GDK_Q: return keymap::Q;
|
||||
case GDK_R: return keymap::R;
|
||||
case GDK_S: return keymap::S;
|
||||
case GDK_T: return keymap::T;
|
||||
case GDK_U: return keymap::U;
|
||||
case GDK_V: return keymap::V;
|
||||
case GDK_W: return keymap::W;
|
||||
case GDK_X: return keymap::X;
|
||||
case GDK_Y: return keymap::Y;
|
||||
case GDK_Z: return keymap::Z;
|
||||
|
||||
case GDK_bracketleft: return keymap::lbracket;
|
||||
case GDK_bracketright: return keymap::rbracket;
|
||||
case GDK_backslash: return keymap::backslash;
|
||||
case GDK_semicolon: return keymap::semicolon;
|
||||
case GDK_apostrophe: return keymap::apostrophe;
|
||||
case GDK_comma: return keymap::comma;
|
||||
case GDK_period: return keymap::period;
|
||||
case GDK_slash: return keymap::slash;
|
||||
|
||||
case GDK_braceleft: return keymap::lbrace;
|
||||
case GDK_braceright: return keymap::rbrace;
|
||||
case GDK_bar: return keymap::pipe;
|
||||
case GDK_colon: return keymap::colon;
|
||||
case GDK_quotedbl: return keymap::quote;
|
||||
case GDK_less: return keymap::lcaret;
|
||||
case GDK_greater: return keymap::rcaret;
|
||||
case GDK_question: return keymap::question;
|
||||
|
||||
case GDK_KP_1: return keymap::kp_1;
|
||||
case GDK_KP_2: return keymap::kp_2;
|
||||
case GDK_KP_3: return keymap::kp_3;
|
||||
case GDK_KP_4: return keymap::kp_4;
|
||||
case GDK_KP_5: return keymap::kp_5;
|
||||
case GDK_KP_6: return keymap::kp_6;
|
||||
case GDK_KP_7: return keymap::kp_7;
|
||||
case GDK_KP_8: return keymap::kp_8;
|
||||
case GDK_KP_9: return keymap::kp_9;
|
||||
case GDK_KP_0: return keymap::kp_0;
|
||||
case GDK_KP_Decimal: return keymap::kp_decimal;
|
||||
|
||||
case GDK_KP_End: return keymap::kp_end;
|
||||
case GDK_KP_Down: return keymap::kp_down;
|
||||
case GDK_KP_Page_Down: return keymap::kp_page_down;
|
||||
case GDK_KP_Left: return keymap::kp_left;
|
||||
case GDK_KP_Begin: return keymap::kp_center;
|
||||
case GDK_KP_Right: return keymap::kp_right;
|
||||
case GDK_KP_Home: return keymap::kp_home;
|
||||
case GDK_KP_Up: return keymap::kp_up;
|
||||
case GDK_KP_Page_Up: return keymap::kp_page_up;
|
||||
case GDK_KP_Insert: return keymap::kp_insert;
|
||||
case GDK_KP_Delete: return keymap::kp_delete;
|
||||
|
||||
case GDK_KP_Add: return keymap::kp_plus;
|
||||
case GDK_KP_Subtract: return keymap::kp_minus;
|
||||
case GDK_KP_Multiply: return keymap::kp_mul;
|
||||
case GDK_KP_Divide: return keymap::kp_div;
|
||||
case GDK_KP_Enter: return keymap::kp_enter;
|
||||
|
||||
case GDK_Num_Lock: return keymap::num_lock;
|
||||
case GDK_Caps_Lock: return keymap::caps_lock;
|
||||
|
||||
case GDK_Up: return keymap::up;
|
||||
case GDK_Down: return keymap::down;
|
||||
case GDK_Left: return keymap::left;
|
||||
case GDK_Right: return keymap::right;
|
||||
|
||||
case GDK_Tab: return keymap::tab;
|
||||
case GDK_Return: return keymap::enter;
|
||||
case GDK_space: return keymap::space;
|
||||
|
||||
case GDK_Control_L: return keymap::lctrl;
|
||||
case GDK_Control_R: return keymap::rctrl;
|
||||
case GDK_Alt_L: return keymap::lalt;
|
||||
case GDK_Alt_R: return keymap::ralt;
|
||||
case GDK_Shift_L: return keymap::lshift;
|
||||
case GDK_Shift_R: return keymap::rshift;
|
||||
case GDK_Super_L: return keymap::lsuper;
|
||||
case GDK_Super_R: return keymap::rsuper;
|
||||
case GDK_Menu: return keymap::menu;
|
||||
}
|
||||
|
||||
return keymap::none;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
void pLabel::create(uint style, uint width, uint height, const char *text) {
|
||||
label = gtk_label_new(text ? text : "");
|
||||
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
|
||||
gtk_widget_set_size_request(label, width, height);
|
||||
gtk_widget_show(label);
|
||||
}
|
||||
|
||||
void pLabel::set_text(const char *text) {
|
||||
if(!label) return;
|
||||
gtk_label_set_label(GTK_LABEL(label), text ? text : "");
|
||||
}
|
||||
|
||||
pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) {
|
||||
label = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pLabel::gtk_handle() {
|
||||
return label;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class pLabel : public pFormControl {
|
||||
public:
|
||||
Label &self;
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
pLabel(Label&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *label;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,135 @@
|
||||
void miu_plistbox_change(pListbox *p) {
|
||||
if(p->listbox_selection == p->get_selection()) return;
|
||||
if(p->self.on_change) p->self.on_change(Event(Event::Change, p->listbox_selection = p->get_selection(), &p->self));
|
||||
}
|
||||
|
||||
void miu_plistbox_activate(pListbox *p) {
|
||||
if(p->self.on_activate) p->self.on_activate(Event(Event::Activate, p->listbox_selection = p->get_selection(), &p->self));
|
||||
}
|
||||
|
||||
void pListbox::create(uint style, uint width, uint height, const char *columns, const char *text) {
|
||||
bool header = style & Listbox::Header;
|
||||
GtkPolicyType hscroll = (style & Listbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Listbox::HorizontalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
GtkPolicyType vscroll = (style & Listbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||
(style & Listbox::VerticalScrollNever) ? GTK_POLICY_NEVER :
|
||||
GTK_POLICY_AUTOMATIC;
|
||||
|
||||
scrollbox = gtk_scrolled_window_new(0, 0);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
||||
|
||||
lstring list;
|
||||
split(list, "\t", columns);
|
||||
|
||||
GType *v = (GType*)malloc(count(list) * sizeof(GType));
|
||||
for(uint i = 0; i < count(list); i++) v[i] = G_TYPE_STRING;
|
||||
store = gtk_list_store_newv(count(list), v);
|
||||
safe_free(v);
|
||||
|
||||
listbox = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
|
||||
gtk_container_add(GTK_CONTAINER(scrollbox), listbox);
|
||||
g_object_unref(G_OBJECT(store));
|
||||
gtk_widget_set_size_request(scrollbox, width, height);
|
||||
gtk_widget_show(listbox);
|
||||
gtk_widget_show(scrollbox);
|
||||
|
||||
//alternate colors for each listbox entry if there are multiple columns ...
|
||||
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(listbox), count(list) >= 2 ? true : false);
|
||||
for(uint i = 0; i < count(list); i++) {
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
column = gtk_tree_view_column_new_with_attributes(list[i], renderer, "text", i, 0);
|
||||
column_list[column_list.size()] = column;
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(listbox), column);
|
||||
}
|
||||
|
||||
if(text && *text) {
|
||||
split(list, "\n", text);
|
||||
for(uint i = 0; i < count(list); i++) add_item(list[i]);
|
||||
}
|
||||
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(listbox), header);
|
||||
autosize_columns();
|
||||
|
||||
g_signal_connect_swapped(G_OBJECT(listbox), "cursor-changed", G_CALLBACK(miu_plistbox_change), (gpointer)this);
|
||||
g_signal_connect_swapped(G_OBJECT(listbox), "row-activated", G_CALLBACK(miu_plistbox_activate), (gpointer)this);
|
||||
}
|
||||
|
||||
void pListbox::autosize_columns() {
|
||||
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listbox));
|
||||
}
|
||||
|
||||
void pListbox::set_column_width(uint column, uint width) {
|
||||
gtk_tree_view_column_set_min_width(column_list[column], width);
|
||||
gtk_tree_view_column_set_max_width(column_list[column], width);
|
||||
}
|
||||
|
||||
void pListbox::add_item(const char *text) {
|
||||
lstring list;
|
||||
split(list, "\t", text);
|
||||
gtk_list_store_append(store, &iter);
|
||||
for(uint i = 0; i < count(list); i++) {
|
||||
gtk_list_store_set(store, &iter, i, list[i](), -1);
|
||||
}
|
||||
}
|
||||
|
||||
void pListbox::set_item(uint index, const char *text) {
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||
for(uint i = 0; i <= index; i++) {
|
||||
i == 0 ?
|
||||
gtk_tree_model_get_iter_first(model, &iter) :
|
||||
gtk_tree_model_iter_next(model, &iter);
|
||||
}
|
||||
|
||||
lstring list;
|
||||
split(list, "\t", text);
|
||||
for(uint i = 0; i < count(list); i++) {
|
||||
gtk_list_store_set(store, &iter, i, list[i](), -1);
|
||||
}
|
||||
}
|
||||
|
||||
int pListbox::get_selection() {
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) { return -1; }
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) { return 0; }
|
||||
for(uint i = 1; i < 100000; i++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) { return -1; }
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) { return i; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pListbox::set_selection(int index) {
|
||||
int current = get_selection();
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||
gtk_tree_selection_unselect_all(selection);
|
||||
if(index < 0) { goto end; }
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; }
|
||||
if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
||||
for(uint i = 1; i < 100000; i++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; }
|
||||
if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
||||
}
|
||||
end:
|
||||
if(current != index) ;//{ owner->message(Message::Changed, (uintptr_t)this); }
|
||||
}
|
||||
|
||||
void pListbox::reset() {
|
||||
gtk_list_store_clear(GTK_LIST_STORE(store));
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(listbox), GTK_TREE_MODEL(store));
|
||||
}
|
||||
|
||||
pListbox::pListbox(Listbox &self_) : pFormControl(self_), self(self_) {
|
||||
scrollbox = 0;
|
||||
listbox = 0;
|
||||
listbox_selection = -1;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pListbox::gtk_handle() {
|
||||
return scrollbox;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
class pListbox : public pFormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *columns = "", const char *text = "");
|
||||
void autosize_columns();
|
||||
void set_column_width(uint column, uint width);
|
||||
void add_item(const char *text);
|
||||
void set_item(uint index, const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
Listbox &self;
|
||||
pListbox(Listbox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *scrollbox;
|
||||
GtkWidget *listbox;
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
array<GtkTreeViewColumn*> column_list;
|
||||
GtkTreeIter iter;
|
||||
int listbox_selection;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
void miu_pmenucheckitem_tick(pMenuCheckItem *p) {
|
||||
if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, p->checked(), &p->self));
|
||||
}
|
||||
|
||||
void pMenuCheckItem::create(const char *text) {
|
||||
item = gtk_check_menu_item_new_with_label(text ? text : "?");
|
||||
gtk_widget_show(item);
|
||||
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(miu_pmenucheckitem_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pMenuCheckItem::check(bool state) {
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), state ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void pMenuCheckItem::uncheck() {
|
||||
check(false);
|
||||
}
|
||||
|
||||
bool pMenuCheckItem::checked() {
|
||||
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
|
||||
}
|
||||
|
||||
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuCheckItem::gtk_handle() {
|
||||
return item;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
class pMenuCheckItem : public pMenuControl {
|
||||
public:
|
||||
void create(const char *text = "");
|
||||
void check(bool state = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
MenuCheckItem &self;
|
||||
pMenuCheckItem(MenuCheckItem&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
void pMenuControl::enable(bool state) {
|
||||
gtk_widget_set_sensitive(gtk_handle(), state);
|
||||
}
|
||||
|
||||
void pMenuControl::disable() {
|
||||
enable(false);
|
||||
}
|
||||
|
||||
bool pMenuControl::enabled() {
|
||||
return GTK_WIDGET_SENSITIVE(gtk_handle());
|
||||
}
|
||||
|
||||
pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) {
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuControl::gtk_handle() {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class pMenuControl : public pWidget {
|
||||
public:
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
MenuControl &self;
|
||||
pMenuControl(MenuControl&);
|
||||
|
||||
/* internal */
|
||||
virtual GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
void pMenuGroup::create(const char *text) {
|
||||
group = gtk_menu_new();
|
||||
item = gtk_menu_item_new_with_label(text ? text : "");
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), group);
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
|
||||
void pMenuGroup::attach(MenuControl &menucontrol) {
|
||||
gtk_menu_shell_append(GTK_MENU_SHELL(group), menucontrol.p.gtk_handle());
|
||||
}
|
||||
|
||||
pMenuGroup::pMenuGroup(MenuGroup &self_) : pMenuControl(self_), self(self_) {
|
||||
group = 0;
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuGroup::gtk_handle() {
|
||||
return item;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class pMenuGroup : public pMenuControl {
|
||||
public:
|
||||
MenuGroup &self;
|
||||
void create(const char *text);
|
||||
void attach(MenuControl &menucontrol);
|
||||
|
||||
pMenuGroup(MenuGroup&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *group;
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
void miu_pmenuitem_tick(pMenuItem *p) {
|
||||
if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pMenuItem::create(const char *text) {
|
||||
item = gtk_menu_item_new_with_label(text ? text : "");
|
||||
g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(miu_pmenuitem_tick), (gpointer)this);
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
|
||||
pMenuItem::pMenuItem(MenuItem &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuItem::gtk_handle() {
|
||||
return item;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class pMenuItem : public pMenuControl {
|
||||
public:
|
||||
void create(const char *text = "");
|
||||
|
||||
MenuItem &self;
|
||||
pMenuItem(MenuItem&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
void miu_pmenuradioitem_tick(pMenuRadioItem *p) {
|
||||
//GTK+ sends two messages: one for the activated radio item,
|
||||
//and one for the deactivated radio item. ignore the latter.
|
||||
if(p->checked() && p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pMenuRadioItem::create(MenuRadioItemGroup &group, const char *text) {
|
||||
if(group.size() == 0 || group[0] == &self) {
|
||||
item = gtk_radio_menu_item_new_with_label(0, text ? text : "?");
|
||||
} else {
|
||||
item = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(group[0]->p.gtk_handle()), text ? text : "");
|
||||
}
|
||||
gtk_widget_show(item);
|
||||
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(miu_pmenuradioitem_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pMenuRadioItem::check() {
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
|
||||
}
|
||||
|
||||
bool pMenuRadioItem::checked() {
|
||||
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
|
||||
}
|
||||
|
||||
pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuRadioItem::gtk_handle() {
|
||||
return item;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class pMenuRadioItem : public pMenuControl {
|
||||
public:
|
||||
void create(MenuRadioItemGroup &group, const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
MenuRadioItem &self;
|
||||
pMenuRadioItem(MenuRadioItem&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
void pMenuSeparator::create() {
|
||||
item = gtk_separator_menu_item_new();
|
||||
gtk_widget_show(item);
|
||||
}
|
||||
|
||||
pMenuSeparator::pMenuSeparator(MenuSeparator &self_) : pMenuControl(self_), self(self_) {
|
||||
item = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pMenuSeparator::gtk_handle() {
|
||||
return item;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class pMenuSeparator : public pMenuControl {
|
||||
public:
|
||||
MenuSeparator &self;
|
||||
void create();
|
||||
|
||||
pMenuSeparator(MenuSeparator&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *item;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
void pProgressbar::create(uint style, uint width, uint height) {
|
||||
progressbar = gtk_progress_bar_new();
|
||||
gtk_widget_set_size_request(progressbar, width, height);
|
||||
gtk_widget_show(progressbar);
|
||||
}
|
||||
|
||||
uint pProgressbar::get_progress() {
|
||||
uint progress = (uint)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar)) * 100.0);
|
||||
return max(0, min(progress, 100));
|
||||
}
|
||||
|
||||
void pProgressbar::set_progress(uint progress) {
|
||||
progress = max(0, min(progress, 100));
|
||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), (double)progress / 100.0);
|
||||
}
|
||||
|
||||
pProgressbar::pProgressbar(Progressbar &self_) : pFormControl(self_), self(self_) {
|
||||
progressbar = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pProgressbar::gtk_handle() {
|
||||
return progressbar;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class pProgressbar : public pFormControl {
|
||||
public:
|
||||
Progressbar &self;
|
||||
void create(uint style, uint width, uint height);
|
||||
uint get_progress();
|
||||
void set_progress(uint progress);
|
||||
|
||||
pProgressbar(Progressbar&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *progressbar;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
void miu_pradiobox_tick(pRadiobox *p) {
|
||||
//GTK+ sends two messages: one for the activated radiobox,
|
||||
//and one for the deactivated radiobox. ignore the latter.
|
||||
if(p->checked() && p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
||||
}
|
||||
|
||||
void pRadiobox::create(RadioboxGroup &group, uint style, uint width, uint height, const char *text) {
|
||||
if(group.size() == 0 || group[0] == &self) {
|
||||
radiobox = gtk_radio_button_new_with_label(0, text ? text : "");
|
||||
} else {
|
||||
radiobox = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(group[0]->p.gtk_handle()), text ? text : "");
|
||||
}
|
||||
gtk_widget_set_size_request(radiobox, width, height);
|
||||
gtk_widget_show(radiobox);
|
||||
g_signal_connect_swapped(G_OBJECT(radiobox), "toggled", G_CALLBACK(miu_pradiobox_tick), (gpointer)this);
|
||||
}
|
||||
|
||||
void pRadiobox::set_text(const char *text) {
|
||||
if(!radiobox) return;
|
||||
gtk_button_set_label(GTK_BUTTON(radiobox), text ? text : "");
|
||||
}
|
||||
|
||||
void pRadiobox::check() {
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobox), TRUE);
|
||||
}
|
||||
|
||||
bool pRadiobox::checked() {
|
||||
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radiobox));
|
||||
}
|
||||
|
||||
pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self), self(self_) {
|
||||
radiobox = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pRadiobox::gtk_handle() {
|
||||
return radiobox;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
class pRadiobox : public pFormControl {
|
||||
public:
|
||||
void create(RadioboxGroup &group, uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
Radiobox &self;
|
||||
pRadiobox(Radiobox&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *radiobox;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
void miu_pslider_change(pSlider *p) {
|
||||
if(p->slider_position == p->get_position()) return;
|
||||
if(p->self.on_change) p->self.on_change(Event(Event::Change, p->slider_position = p->get_position(), &p->self));
|
||||
}
|
||||
|
||||
void pSlider::create(uint style, uint width, uint height, uint length) {
|
||||
if(length < 1) length = 1;
|
||||
if(style & Slider::Vertical) {
|
||||
slider = gtk_vscale_new_with_range(0, length - 1, 1);
|
||||
} else {
|
||||
slider = gtk_hscale_new_with_range(0, length - 1, 1);
|
||||
}
|
||||
gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE);
|
||||
gtk_widget_set_size_request(slider, width, height);
|
||||
gtk_widget_show(slider);
|
||||
g_signal_connect_swapped(G_OBJECT(slider), "value-changed", G_CALLBACK(miu_pslider_change), (gpointer)this);
|
||||
}
|
||||
|
||||
uint pSlider::get_position() {
|
||||
return (uint)gtk_range_get_value(GTK_RANGE(slider));
|
||||
}
|
||||
|
||||
void pSlider::set_position(uint position) {
|
||||
gtk_range_set_value(GTK_RANGE(slider), position);
|
||||
}
|
||||
|
||||
pSlider::pSlider(Slider &self_) : pFormControl(self_), self(self_) {
|
||||
slider = 0;
|
||||
slider_position = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pSlider::gtk_handle() {
|
||||
return slider;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
class pSlider : public pFormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, uint length);
|
||||
uint get_position();
|
||||
void set_position(uint position);
|
||||
|
||||
Slider &self;
|
||||
pSlider(Slider&);
|
||||
|
||||
/* internal */
|
||||
GtkWidget *slider;
|
||||
uint slider_position;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
void pWidget::show(bool state) {
|
||||
state ? gtk_widget_show(gtk_handle()) : gtk_widget_hide(gtk_handle());
|
||||
}
|
||||
|
||||
void pWidget::hide() {
|
||||
show(false);
|
||||
}
|
||||
|
||||
bool pWidget::visible() {
|
||||
return GTK_WIDGET_VISIBLE(gtk_handle());
|
||||
}
|
||||
|
||||
uintptr_t pWidget::handle() {
|
||||
return GDK_WINDOW_XWINDOW(gtk_handle()->window);
|
||||
}
|
||||
|
||||
pWidget::pWidget(Widget &self_) : self(self_) {
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pWidget::gtk_handle() {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class pWidget {
|
||||
public:
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
uintptr_t handle();
|
||||
|
||||
Widget &self;
|
||||
pWidget(Widget&);
|
||||
|
||||
/* internal */
|
||||
virtual GtkWidget* gtk_handle();
|
||||
};
|
||||
@@ -0,0 +1,135 @@
|
||||
gint miu_pwindow_close(pWindow *p) {
|
||||
uintptr_t r = p->self.on_close ? p->self.on_close(Event(Event::Close, 0, &p->self)) : true;
|
||||
return !bool(r);
|
||||
}
|
||||
|
||||
gint miu_pwindow_keydown(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
||||
if(p && p->self.on_keydown) p->self.on_keydown(Event(Event::KeyDown, pmiu().translate_key(key->keyval), &p->self));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gint miu_pwindow_keyup(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
||||
if(p && p->self.on_keyup) p->self.on_keyup(Event(Event::KeyUp, pmiu().translate_key(key->keyval), &p->self));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void pWindow::create(uint style, uint width, uint height, const char *text) {
|
||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title(GTK_WINDOW(window), text ? text : "");
|
||||
gtk_window_set_resizable(GTK_WINDOW(window), false);
|
||||
if(style & Window::AutoCenter) gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
|
||||
g_signal_connect_swapped(G_OBJECT(window), "delete_event", G_CALLBACK(miu_pwindow_close), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(miu_pwindow_keydown), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(miu_pwindow_keyup), (gpointer)this);
|
||||
|
||||
menucontainer = gtk_vbox_new(false, 0);
|
||||
gtk_container_add(GTK_CONTAINER(window), menucontainer);
|
||||
gtk_widget_show(menucontainer);
|
||||
|
||||
menubar = gtk_menu_bar_new();
|
||||
gtk_box_pack_start(GTK_BOX(menucontainer), menubar, false, false, 0);
|
||||
|
||||
formcontainer = gtk_fixed_new();
|
||||
gtk_widget_set_size_request(formcontainer, width, height);
|
||||
gtk_box_pack_end(GTK_BOX(menucontainer), formcontainer, true, true, 0);
|
||||
gtk_widget_show(formcontainer);
|
||||
}
|
||||
|
||||
void pWindow::close() {
|
||||
gtk_widget_destroy(window);
|
||||
}
|
||||
|
||||
void pWindow::move(uint x, uint y) {
|
||||
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
|
||||
gtk_window_move(GTK_WINDOW(window), x, y);
|
||||
}
|
||||
|
||||
void pWindow::resize(uint width, uint height) {
|
||||
gtk_widget_set_size_request(formcontainer, width, height);
|
||||
}
|
||||
|
||||
void pWindow::focus() {
|
||||
gtk_window_present(GTK_WINDOW(window));
|
||||
}
|
||||
|
||||
bool pWindow::focused() {
|
||||
return gtk_window_is_active(GTK_WINDOW(window));
|
||||
}
|
||||
|
||||
void pWindow::fullscreen() {
|
||||
gtk_window_fullscreen(GTK_WINDOW(window));
|
||||
}
|
||||
|
||||
void pWindow::unfullscreen() {
|
||||
gtk_window_unfullscreen(GTK_WINDOW(window));
|
||||
}
|
||||
|
||||
void pWindow::set_background_color(uint8 r, uint8 g, uint8 b) {
|
||||
GdkColor color;
|
||||
color.pixel = (r << 16) | (g << 8) | b;
|
||||
color.red = (r << 8) | r;
|
||||
color.green = (g << 8) | g;
|
||||
color.blue = (b << 8) | b;
|
||||
gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);
|
||||
gtk_widget_modify_bg(formcontainer, GTK_STATE_NORMAL, &color);
|
||||
}
|
||||
|
||||
void pWindow::set_text(const char *text) {
|
||||
gtk_window_set_title(GTK_WINDOW(window), text ? text : "");
|
||||
}
|
||||
|
||||
void pWindow::attach(Window &window, uint x, uint y) {
|
||||
window.p.owner = this;
|
||||
//GTK+ does not support attaching a window to another window,
|
||||
//so instead reparent the container from the child window to
|
||||
//the parent window, and reposition the child window's container
|
||||
gtk_widget_hide(window.p.window);
|
||||
gtk_widget_hide(window.p.formcontainer);
|
||||
gtk_widget_reparent(window.p.formcontainer, formcontainer);
|
||||
gtk_fixed_move(GTK_FIXED(formcontainer), window.p.formcontainer, x, y);
|
||||
gtk_widget_show(window.p.formcontainer);
|
||||
}
|
||||
|
||||
void pWindow::attach(MenuGroup &menugroup) {
|
||||
gtk_menu_bar_append(menubar, menugroup.p.item);
|
||||
gtk_widget_show(menubar);
|
||||
}
|
||||
|
||||
void pWindow::attach(FormControl &formcontrol, uint x, uint y) {
|
||||
gtk_fixed_put(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
||||
}
|
||||
|
||||
void pWindow::move(Window &window, uint x, uint y) {
|
||||
gtk_fixed_move(GTK_FIXED(formcontainer), window.p.gtk_handle(), x, y);
|
||||
}
|
||||
|
||||
void pWindow::move(FormControl &formcontrol, uint x, uint y) {
|
||||
gtk_fixed_move(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
||||
}
|
||||
|
||||
void pWindow::menu_show(bool state) {
|
||||
if(!menubar) return;
|
||||
state ? gtk_widget_show(menubar) : gtk_widget_hide(menubar);
|
||||
}
|
||||
|
||||
void pWindow::menu_hide() {
|
||||
menu_show(false);
|
||||
}
|
||||
|
||||
bool pWindow::menu_visible() {
|
||||
return GTK_WIDGET_VISIBLE(menubar);
|
||||
}
|
||||
|
||||
pWindow::pWindow(Window &self_) : pWidget(self_), self(self_) {
|
||||
owner = 0;
|
||||
window = 0;
|
||||
menubar = 0;
|
||||
menucontainer = 0;
|
||||
formcontainer = 0;
|
||||
}
|
||||
|
||||
/* internal */
|
||||
|
||||
GtkWidget* pWindow::gtk_handle() {
|
||||
return owner ? formcontainer : window;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
class pWindow : public pWidget {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void close();
|
||||
void move(uint x, uint y);
|
||||
void resize(uint width, uint height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void fullscreen();
|
||||
void unfullscreen();
|
||||
void set_background_color(uint8 r, uint8 g, uint8 b);
|
||||
void set_text(const char *text = "");
|
||||
void attach(Window &window, uint x, uint y);
|
||||
void attach(MenuGroup &menugroup);
|
||||
void attach(FormControl &formcontrol, uint x, uint y);
|
||||
void move(Window &window, uint x, uint y);
|
||||
void move(FormControl &formcontrol, uint x, uint y);
|
||||
void menu_show(bool state = true);
|
||||
void menu_hide();
|
||||
bool menu_visible();
|
||||
|
||||
Window &self;
|
||||
pWindow(Window&);
|
||||
|
||||
/* internal */
|
||||
pWindow *owner; //0 = no owner (default)
|
||||
GtkWidget *window;
|
||||
GtkWidget *menubar;
|
||||
GtkWidget *menucontainer;
|
||||
GtkWidget *formcontainer;
|
||||
GtkWidget* gtk_handle();
|
||||
};
|
||||
+506
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
miu
|
||||
version: 0.012 (2007-12-22)
|
||||
author: byuu
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef MIU_H
|
||||
#define MIU_H
|
||||
|
||||
#include "bbase.h"
|
||||
#include "barray.h"
|
||||
#include "bfunction.h"
|
||||
#include "bkeymap.h"
|
||||
#include "bstring.h"
|
||||
|
||||
namespace ns_miu {
|
||||
|
||||
class pMiu;
|
||||
class pWidget;
|
||||
class pWindow;
|
||||
class pMenuControl;
|
||||
class pMenuGroup;
|
||||
class pMenuItem;
|
||||
class pMenuCheckItem;
|
||||
class pMenuRadioItem;
|
||||
class pMenuSeparator;
|
||||
class pFormControl;
|
||||
class pFrame;
|
||||
class pCanvas;
|
||||
class pLabel;
|
||||
class pButton;
|
||||
class pCheckbox;
|
||||
class pRadiobox;
|
||||
class pEditbox;
|
||||
class pListbox;
|
||||
class pCombobox;
|
||||
class pProgressbar;
|
||||
class pSlider;
|
||||
|
||||
#define pFriends \
|
||||
friend class pMiu; \
|
||||
friend class pWidget; \
|
||||
friend class pWindow; \
|
||||
friend class pMenuControl; \
|
||||
friend class pMenuGroup; \
|
||||
friend class pMenuItem; \
|
||||
friend class pMenuCheckItem; \
|
||||
friend class pMenuRadioItem; \
|
||||
friend class pMenuSeparator; \
|
||||
friend class pFormControl; \
|
||||
friend class pFrame; \
|
||||
friend class pCanvas; \
|
||||
friend class pLabel; \
|
||||
friend class pButton; \
|
||||
friend class pCheckbox; \
|
||||
friend class pRadiobox; \
|
||||
friend class pEditbox; \
|
||||
friend class pListbox; \
|
||||
friend class pCombobox; \
|
||||
friend class pProgressbar; \
|
||||
friend class pSlider
|
||||
|
||||
class Miu;
|
||||
class Widget;
|
||||
class Window;
|
||||
class MenuControl;
|
||||
class MenuGroup;
|
||||
class MenuItem;
|
||||
class MenuCheckItem;
|
||||
class MenuRadioItem;
|
||||
class MenuSeparator;
|
||||
class FormControl;
|
||||
class Frame;
|
||||
class Canvas;
|
||||
class Label;
|
||||
class Button;
|
||||
class Checkbox;
|
||||
class Radiobox;
|
||||
class Editbox;
|
||||
class Listbox;
|
||||
class Combobox;
|
||||
class Progressbar;
|
||||
class Slider;
|
||||
|
||||
typedef array<MenuRadioItem*> MenuRadioItemGroup;
|
||||
typedef array<Radiobox*> RadioboxGroup;
|
||||
|
||||
struct Event {
|
||||
enum Type {
|
||||
Close,
|
||||
Block,
|
||||
KeyDown,
|
||||
KeyUp,
|
||||
Change,
|
||||
Tick,
|
||||
Activate,
|
||||
} type;
|
||||
uintptr_t param;
|
||||
Widget *widget;
|
||||
|
||||
Event(Type type_, uintptr_t param_ = 0, Widget *widget_ = 0) :
|
||||
type(type_), param(param_), widget(widget_) {}
|
||||
};
|
||||
|
||||
class Miu : noncopyable {
|
||||
public:
|
||||
void init();
|
||||
void term();
|
||||
bool run();
|
||||
bool pending();
|
||||
|
||||
bool file_load(Window *focus, char *filename, const char *filter, const char *path);
|
||||
bool file_save(Window *focus, char *filename, const char *filter, const char *path);
|
||||
|
||||
uint screen_width();
|
||||
uint screen_height();
|
||||
|
||||
static Miu& handle();
|
||||
Miu();
|
||||
~Miu();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMiu &p;
|
||||
};
|
||||
|
||||
Miu& miu();
|
||||
|
||||
class Widget : noncopyable {
|
||||
public:
|
||||
enum Type {
|
||||
WidgetType,
|
||||
WindowType,
|
||||
MenuControlType,
|
||||
MenuGroupType,
|
||||
MenuItemType,
|
||||
MenuCheckItemType,
|
||||
MenuRadioItemType,
|
||||
MenuSeparatorType,
|
||||
FormControlType,
|
||||
FrameType,
|
||||
CanvasType,
|
||||
LabelType,
|
||||
ButtonType,
|
||||
CheckboxType,
|
||||
RadioboxType,
|
||||
EditboxType,
|
||||
ListboxType,
|
||||
ComboboxType,
|
||||
ProgressbarType,
|
||||
SliderType,
|
||||
} type;
|
||||
|
||||
void show(bool = true);
|
||||
void hide();
|
||||
bool visible();
|
||||
|
||||
uintptr_t handle();
|
||||
|
||||
Widget();
|
||||
~Widget();
|
||||
|
||||
protected:
|
||||
Widget(pWidget&);
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pWidget &p;
|
||||
};
|
||||
|
||||
class Window : private base_from_member<pWindow&>, public Widget {
|
||||
public:
|
||||
enum Style {
|
||||
AutoCenter = 1 << 1,
|
||||
};
|
||||
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void close();
|
||||
void move(uint x, uint y);
|
||||
void resize(uint width, uint height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void fullscreen();
|
||||
void unfullscreen();
|
||||
void set_background_color(uint8 r, uint8 g, uint8 b);
|
||||
void set_text(const char *text = "");
|
||||
void attach(Window &window, uint x, uint y);
|
||||
void attach(MenuGroup &menugroup);
|
||||
void attach(FormControl &formcontrol, uint x, uint y);
|
||||
void move(Window &window, uint x, uint y);
|
||||
void move(FormControl &formcontrol, uint x, uint y);
|
||||
void menu_show(bool = true);
|
||||
void menu_hide();
|
||||
bool menu_visible();
|
||||
|
||||
function<uintptr_t (Event)> on_close;
|
||||
function<uintptr_t (Event)> on_block;
|
||||
function<uintptr_t (Event)> on_keydown;
|
||||
function<uintptr_t (Event)> on_keyup;
|
||||
|
||||
Window();
|
||||
|
||||
protected:
|
||||
Window(pWindow&);
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pWindow &p;
|
||||
};
|
||||
|
||||
class MenuControl : public base_from_member<pMenuControl&>, public Widget {
|
||||
public:
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
MenuControl();
|
||||
|
||||
protected:
|
||||
MenuControl(pMenuControl&);
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuControl &p;
|
||||
};
|
||||
|
||||
class MenuGroup : public base_from_member<pMenuGroup&>, public MenuControl {
|
||||
public:
|
||||
MenuGroup& create(const char *text);
|
||||
void attach(MenuControl &menucontrol);
|
||||
MenuGroup();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuGroup &p;
|
||||
};
|
||||
|
||||
class MenuItem : public base_from_member<pMenuItem&>, public MenuControl {
|
||||
public:
|
||||
MenuItem& create(const char *text);
|
||||
MenuItem();
|
||||
|
||||
function<uintptr_t (Event)> on_tick;
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuItem &p;
|
||||
};
|
||||
|
||||
class MenuCheckItem : public base_from_member<pMenuCheckItem&>, public MenuControl {
|
||||
public:
|
||||
MenuCheckItem& create(const char *text);
|
||||
void check(bool = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
MenuCheckItem();
|
||||
|
||||
function<uintptr_t (Event)> on_tick;
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuCheckItem &p;
|
||||
};
|
||||
|
||||
class MenuRadioItem : public base_from_member<pMenuRadioItem&>, public MenuControl {
|
||||
public:
|
||||
MenuRadioItem& create(MenuRadioItemGroup &group, const char *text);
|
||||
void check();
|
||||
bool checked();
|
||||
MenuRadioItem();
|
||||
|
||||
function<uintptr_t (Event)> on_tick;
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuRadioItem &p;
|
||||
};
|
||||
|
||||
class MenuSeparator : public base_from_member<pMenuSeparator&>, public MenuControl {
|
||||
public:
|
||||
MenuSeparator& create();
|
||||
MenuSeparator();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pMenuSeparator &p;
|
||||
};
|
||||
|
||||
class FormControl : private base_from_member<pFormControl&>, public Widget {
|
||||
public:
|
||||
void resize(uint width, uint height);
|
||||
void focus();
|
||||
bool focused();
|
||||
void enable(bool = true);
|
||||
void disable();
|
||||
bool enabled();
|
||||
|
||||
FormControl();
|
||||
|
||||
protected:
|
||||
FormControl(pFormControl&);
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pFormControl &p;
|
||||
};
|
||||
|
||||
class Frame : private base_from_member<pFrame&>, public FormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
Frame();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pFrame &p;
|
||||
};
|
||||
|
||||
class Canvas : private base_from_member<pCanvas&>, public FormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height);
|
||||
void redraw();
|
||||
uint32* buffer();
|
||||
|
||||
Canvas();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pCanvas &p;
|
||||
};
|
||||
|
||||
class Label : private base_from_member<pLabel&>, public FormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
Label();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pLabel &p;
|
||||
};
|
||||
|
||||
class Button : private base_from_member<pButton&>, public FormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
|
||||
function<uintptr_t (Event)> on_tick;
|
||||
|
||||
Button();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pButton &p;
|
||||
};
|
||||
|
||||
class Checkbox : private base_from_member<pCheckbox&>, public FormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check(bool = true);
|
||||
void uncheck();
|
||||
bool checked();
|
||||
|
||||
function<uintptr_t (Event)> on_tick;
|
||||
|
||||
Checkbox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pCheckbox &p;
|
||||
};
|
||||
|
||||
class Radiobox : private base_from_member<pRadiobox&>, public FormControl {
|
||||
public:
|
||||
void create(RadioboxGroup &group, uint style, uint width, uint height, const char *text = "");
|
||||
void set_text(const char *text = "");
|
||||
void check();
|
||||
bool checked();
|
||||
|
||||
function<uintptr_t (Event)> on_tick;
|
||||
|
||||
Radiobox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pRadiobox &p;
|
||||
};
|
||||
|
||||
class Editbox : private base_from_member<pEditbox&>, public FormControl {
|
||||
public:
|
||||
enum Style {
|
||||
Multiline = 1 << 1,
|
||||
Readonly = 1 << 2,
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = 1 << 3,
|
||||
HorizontalScrollNever = 1 << 4,
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = 1 << 5,
|
||||
VerticalScrollNever = 1 << 6,
|
||||
};
|
||||
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
uint get_text(char *text, uint length = -1U);
|
||||
void set_text(const char *text = "");
|
||||
|
||||
Editbox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pEditbox &p;
|
||||
};
|
||||
|
||||
class Listbox : private base_from_member<pListbox&>, public FormControl {
|
||||
public:
|
||||
enum Style {
|
||||
Header = 1 << 1,
|
||||
|
||||
HorizontalScrollAuto = 0,
|
||||
HorizontalScrollAlways = 1 << 2,
|
||||
HorizontalScrollNever = 1 << 3,
|
||||
|
||||
VerticalScrollAuto = 0,
|
||||
VerticalScrollAlways = 1 << 4,
|
||||
VerticalScrollNever = 1 << 5,
|
||||
};
|
||||
|
||||
void create(uint style, uint width, uint height, const char *columns = "", const char *text = "");
|
||||
void autosize_columns();
|
||||
void set_column_width(uint column, uint width);
|
||||
void add_item(const char *text);
|
||||
void set_item(uint index, const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
function<uintptr_t (Event)> on_change;
|
||||
function<uintptr_t (Event)> on_activate;
|
||||
|
||||
Listbox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pListbox &p;
|
||||
};
|
||||
|
||||
class Combobox : private base_from_member<pCombobox&>, public FormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height, const char *text = "");
|
||||
void add_item(const char *text);
|
||||
int get_selection();
|
||||
void set_selection(int index);
|
||||
void reset();
|
||||
|
||||
function<uintptr_t (Event)> on_change;
|
||||
|
||||
Combobox();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pCombobox &p;
|
||||
};
|
||||
|
||||
class Progressbar : private base_from_member<pProgressbar&>, public FormControl {
|
||||
public:
|
||||
void create(uint style, uint width, uint height);
|
||||
uint get_progress();
|
||||
void set_progress(uint progress);
|
||||
|
||||
Progressbar();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pProgressbar &p;
|
||||
};
|
||||
|
||||
class Slider : private base_from_member<pSlider&>, public FormControl {
|
||||
public:
|
||||
enum Style {
|
||||
Horizontal = 0,
|
||||
Vertical = 1 << 1,
|
||||
};
|
||||
|
||||
void create(uint style, uint width, uint height, uint length);
|
||||
uint get_position();
|
||||
void set_position(uint position);
|
||||
|
||||
function<uintptr_t (Event)> on_change;
|
||||
|
||||
Slider();
|
||||
|
||||
private:
|
||||
pFriends;
|
||||
pSlider &p;
|
||||
};
|
||||
|
||||
#undef pFriends
|
||||
|
||||
} //namespace ns_miu
|
||||
|
||||
#endif //ifndef MIU_H
|
||||
Loaded 100 of 242 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user