c code that doesn’t work
This commit is contained in:
parent
a808187550
commit
2e04c5c77e
5 changed files with 322 additions and 79 deletions
2
Makefile
2
Makefile
|
@ -6,6 +6,8 @@ LOCALEDIR=$(DATADIR)/locale
|
|||
MANDIR=$(DATADIR)/man
|
||||
|
||||
all: Makefile
|
||||
python3 setup.py build
|
||||
cp build/lib.linux-x86_64-3.2/poopt.cpython-32mu.so src/
|
||||
|
||||
clean:
|
||||
find ./ -name \*.pyc -delete
|
||||
|
|
277
src/pooptmodule.c
Normal file
277
src/pooptmodule.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
/* Copyright 2010-2011 Florent Le Coz <louiz@louiz.org> */
|
||||
|
||||
/* This file is part of Poezio. */
|
||||
|
||||
/* Poezio is free software: you can redistribute it and/or modify */
|
||||
/* it under the terms of the MIT license. See the COPYING file. */
|
||||
|
||||
/** The poopt python3 module
|
||||
**/
|
||||
|
||||
/* This file is a python3 module for poezio, used to replace some time-critical
|
||||
python functions that are too slow. If compiled, poezio will use this module,
|
||||
otherwise it will just use the equivalent python functions. */
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
PyObject *ErrorObject;
|
||||
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
/***
|
||||
The module functions
|
||||
***/
|
||||
|
||||
/* cut_text: takes a string and returns a tuple of int.
|
||||
Each two int tuple is a line, represented by the ending position it (where it should be cut).
|
||||
Not that this position is calculed using the position of the python string characters,
|
||||
not just the individual bytes.
|
||||
For example, poopt_cut_text("vivent les frigidaires", 6);
|
||||
will return [(0, 6), (7, 10), (11, 17), (17, 22)], meaning that the lines are
|
||||
"vivent", "les", "frigid" and "aires"
|
||||
*/
|
||||
PyDoc_STRVAR(poopt_cut_text_doc, "cut_text(width, text)\n\n\nReturn the list of strings, cut according to the given size.");
|
||||
|
||||
static PyObject *poopt_cut_text(PyObject *self, PyObject *args)
|
||||
{
|
||||
int length;
|
||||
unsigned char *buffer;
|
||||
int width;
|
||||
|
||||
if (PyArg_ParseTuple(args, "es#i", NULL, &buffer, &length, &width) == 0)
|
||||
return NULL;
|
||||
|
||||
int bpos = 0; /* the real position in the char* */
|
||||
int spos = 0; /* the position, considering UTF-8 chars */
|
||||
int last_space = -1;
|
||||
int start_pos = 0;
|
||||
|
||||
PyObject* retlist = PyList_New(0);
|
||||
|
||||
while (bpos < length)
|
||||
{
|
||||
if (buffer[bpos] == ' ')
|
||||
last_space = spos;
|
||||
else if (buffer[bpos] == '\n')
|
||||
{
|
||||
if (PyList_Append(retlist, Py_BuildValue("ii", start_pos, spos)) == -1)
|
||||
return NULL;
|
||||
start_pos = spos + 1;
|
||||
last_space = -1;
|
||||
}
|
||||
else if ((spos - start_pos) >= width)
|
||||
{
|
||||
if (last_space == -1)
|
||||
{
|
||||
if (PyList_Append(retlist, Py_BuildValue("ii", start_pos, spos)) == -1)
|
||||
return NULL;
|
||||
start_pos = spos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PyList_Append(retlist, Py_BuildValue("ii", start_pos, last_space)) == -1)
|
||||
return NULL;
|
||||
start_pos = last_space + 1;
|
||||
last_space = -1;
|
||||
}
|
||||
}
|
||||
if (buffer[bpos] == 25) /* \x19 */
|
||||
{
|
||||
spos--;
|
||||
bpos += 1;
|
||||
}
|
||||
else if (buffer[bpos] <= 127) /* ASCII char on one byte */
|
||||
bpos += 1;
|
||||
else if (buffer[bpos] <= 195)
|
||||
bpos += 2;
|
||||
else if (buffer[bpos] <= 225)
|
||||
bpos += 3;
|
||||
else
|
||||
bpos += 4;
|
||||
spos++;
|
||||
}
|
||||
if (PyList_Append(retlist, Py_BuildValue("(i,i)", start_pos, spos)) == -1)
|
||||
return NULL;
|
||||
return retlist;
|
||||
}
|
||||
|
||||
/***
|
||||
Module initialization. Just taken from the xxmodule.c template from the python sources.
|
||||
***/
|
||||
static PyTypeObject Str_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"pooptmodule.Str", /*tp_name*/
|
||||
0, /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
0, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_reserved*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
0, /* see PyInit_xx */ /*tp_base*/
|
||||
0, /*tp_dict*/
|
||||
0, /*tp_descr_get*/
|
||||
0, /*tp_descr_set*/
|
||||
0, /*tp_dictoffset*/
|
||||
0, /*tp_init*/
|
||||
0, /*tp_alloc*/
|
||||
0, /*tp_new*/
|
||||
0, /*tp_free*/
|
||||
0, /*tp_is_gc*/
|
||||
};
|
||||
|
||||
/* ---------- */
|
||||
|
||||
static PyObject *
|
||||
null_richcompare(PyObject *self, PyObject *other, int op)
|
||||
{
|
||||
Py_INCREF(Py_NotImplemented);
|
||||
return Py_NotImplemented;
|
||||
}
|
||||
|
||||
static PyTypeObject Null_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"pooptmodule.Null", /*tp_name*/
|
||||
0, /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
0, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_reserved*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
null_richcompare, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
0, /*tp_getset*/
|
||||
0, /* see PyInit_xx */ /*tp_base*/
|
||||
0, /*tp_dict*/
|
||||
0, /*tp_descr_get*/
|
||||
0, /*tp_descr_set*/
|
||||
0, /*tp_dictoffset*/
|
||||
0, /*tp_init*/
|
||||
0, /*tp_alloc*/
|
||||
0, /* see PyInit_xx */ /*tp_new*/
|
||||
0, /*tp_free*/
|
||||
0, /*tp_is_gc*/
|
||||
};
|
||||
|
||||
|
||||
/* List of functions defined in the module */
|
||||
|
||||
static PyMethodDef poopt_methods[] = {
|
||||
{"cut_text", poopt_cut_text, METH_VARARGS,
|
||||
poopt_cut_text_doc},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(module_doc,
|
||||
"This is a template module just for instruction. And poopt.");
|
||||
|
||||
/* Initialization function for the module (*must* be called PyInit_xx) */
|
||||
|
||||
static struct PyModuleDef pooptmodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"poopt",
|
||||
module_doc,
|
||||
-1,
|
||||
poopt_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_poopt(void)
|
||||
{
|
||||
PyObject *m = NULL;
|
||||
|
||||
/* Due to cross platform compiler issues the slots must be filled
|
||||
* here. It's required for portability to Windows without requiring
|
||||
* C++. */
|
||||
Null_Type.tp_base = &PyBaseObject_Type;
|
||||
Null_Type.tp_new = PyType_GenericNew;
|
||||
Str_Type.tp_base = &PyUnicode_Type;
|
||||
|
||||
/* Finalize the type object including setting type of the new type
|
||||
* object; doing it here is required for portability, too. */
|
||||
/* if (PyType_Ready(&Xxo_Type) < 0) */
|
||||
/* goto fail; */
|
||||
|
||||
/* Create the module and add the functions */
|
||||
m = PyModule_Create(&pooptmodule);
|
||||
if (m == NULL)
|
||||
goto fail;
|
||||
|
||||
/* Add some symbolic constants to the module */
|
||||
if (ErrorObject == NULL) {
|
||||
ErrorObject = PyErr_NewException("poopt.error", NULL, NULL);
|
||||
if (ErrorObject == NULL)
|
||||
goto fail;
|
||||
}
|
||||
Py_INCREF(ErrorObject);
|
||||
PyModule_AddObject(m, "error", ErrorObject);
|
||||
|
||||
/* Add Str */
|
||||
if (PyType_Ready(&Str_Type) < 0)
|
||||
goto fail;
|
||||
PyModule_AddObject(m, "Str", (PyObject *)&Str_Type);
|
||||
|
||||
/* Add Null */
|
||||
if (PyType_Ready(&Null_Type) < 0)
|
||||
goto fail;
|
||||
PyModule_AddObject(m, "Null", (PyObject *)&Null_Type);
|
||||
return m;
|
||||
fail:
|
||||
Py_XDECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* /\* test function *\/ */
|
||||
/* int main(void) */
|
||||
/* { */
|
||||
/* char coucou[] = "vive le foutre, le beurre et le caca boudin"; */
|
||||
|
||||
/* cut_text(coucou, 8); */
|
||||
/* } */
|
17
src/room.py
17
src/room.py
|
@ -1,18 +1,9 @@
|
|||
# Copyright 2010-2011 Le Coz Florent <louiz@louiz.org>
|
||||
# Copyright 2010-2011 Florent Le Coz <louiz@louiz.org>
|
||||
#
|
||||
# This file is part of Poezio.
|
||||
#
|
||||
# Poezio is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Poezio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
|
||||
# it under the terms of the MIT license. See the COPYING file.
|
||||
|
||||
from text_buffer import TextBuffer, Message
|
||||
from datetime import datetime
|
||||
|
@ -129,7 +120,9 @@ class Room(TextBuffer):
|
|||
nick_color = highlight
|
||||
time = time or datetime.now()
|
||||
message = Message(txt='%s\x19o'%(txt,), nick_color=nick_color,
|
||||
time=time, nickname=nickname, user=user)
|
||||
time=time, str_time=time.strftime("%Y-%m-%d %H:%M:%S")\
|
||||
if history else time.strftime("%H:%M:%S"),\
|
||||
nickname=nickname, user=user)
|
||||
while len(self.messages) > self.messages_nb_limit:
|
||||
self.messages.pop(0)
|
||||
self.messages.append(message)
|
||||
|
|
|
@ -27,7 +27,7 @@ from datetime import datetime
|
|||
import theme
|
||||
from config import config
|
||||
|
||||
Message = collections.namedtuple('Message', 'txt nick_color time nickname user')
|
||||
Message = collections.namedtuple('Message', 'txt nick_color time str_time nickname user')
|
||||
|
||||
class TextBuffer(object):
|
||||
"""
|
||||
|
@ -45,8 +45,11 @@ class TextBuffer(object):
|
|||
self.windows.append(win)
|
||||
|
||||
def add_message(self, txt, time=None, nickname=None, nick_color=None, history=None):
|
||||
msg = Message(txt='%s\x19o'%(txt,), nick_color=nick_color,
|
||||
time=time or datetime.now(), nickname=nickname, user=None)
|
||||
time = time or datetime.now()
|
||||
msg = Message(txt='%s'%(txt,), nick_color=nick_color,
|
||||
time=time, str_time=time.strftime("%Y-%m-%d %H:%M:%S")\
|
||||
if history else time.strftime("%H:%M:%S"),\
|
||||
nickname=nickname, user=None)
|
||||
self.messages.append(msg)
|
||||
while len(self.messages) > self.messages_nb_limit:
|
||||
self.messages.pop(0)
|
||||
|
|
|
@ -1,18 +1,9 @@
|
|||
# Copyright 2010-2011 Le Coz Florent <louiz@louiz.org>
|
||||
# Copyright 2010-2011 Florent Le Coz <louiz@louiz.org>
|
||||
#
|
||||
# This file is part of Poezio.
|
||||
#
|
||||
# Poezio is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Poezio is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
|
||||
# it under the terms of the MIT license. See the COPYING file.
|
||||
|
||||
"""
|
||||
Define all the windows.
|
||||
|
@ -37,6 +28,7 @@ from threading import Lock
|
|||
|
||||
from contact import Contact, Resource
|
||||
from roster import RosterGroup, roster
|
||||
from poopt import cut_text
|
||||
|
||||
# from message import Line
|
||||
from tabs import MIN_WIDTH, MIN_HEIGHT
|
||||
|
@ -50,7 +42,10 @@ import wcwidth
|
|||
import singleton
|
||||
import collections
|
||||
|
||||
Line = collections.namedtuple('Line', 'text text_offset nickname_color time nickname')
|
||||
# msg is a reference to the corresponding Message tuple. text_start and text_end are the position
|
||||
# delimiting the text in this line.
|
||||
# first is a bool telling if this is the first line of the message.
|
||||
Line = collections.namedtuple('Line', 'msg start_pos end_pos first')
|
||||
|
||||
g_lock = Lock()
|
||||
|
||||
|
@ -544,23 +539,7 @@ class TextWin(Win):
|
|||
Return the number of lines that are built for the given
|
||||
message.
|
||||
"""
|
||||
def cut_text(text, width):
|
||||
"""
|
||||
returns the text that should be displayed on the line, and the rest
|
||||
of the text, in a tuple
|
||||
"""
|
||||
cutted = wcwidth.widthcut(text, width) or text[:width]
|
||||
limit = cutted.find('\n')
|
||||
if limit >= 0:
|
||||
return (text[limit+1:], text[:limit])
|
||||
if not wcwidth.wcsislonger(text, width):
|
||||
return ('', text)
|
||||
limit = cutted.rfind(' ')
|
||||
if limit <= 0:
|
||||
return (text[len(cutted):], cutted)
|
||||
else:
|
||||
return (text[limit+1:], text[:limit])
|
||||
|
||||
log.debug('LEEEN: %s [%s]' % (len(message.txt), repr(message.txt)))
|
||||
if message is None: # line separator
|
||||
self.built_lines.append(None)
|
||||
return 0
|
||||
|
@ -574,7 +553,7 @@ class TextWin(Win):
|
|||
offset = 20
|
||||
else:
|
||||
offset = 9
|
||||
if theme.CHAR_TIME_RIGHT:
|
||||
if theme.CHAR_TIME_LEFT:
|
||||
offset += 1
|
||||
if theme.CHAR_TIME_RIGHT:
|
||||
offset += 1
|
||||
|
@ -586,36 +565,21 @@ class TextWin(Win):
|
|||
if nick:
|
||||
offset += wcwidth.wcswidth(nick) + 2 # + nick + spaces length
|
||||
first = True
|
||||
nb = 0
|
||||
while txt != '':
|
||||
(txt, cutted_txt) = cut_text(txt, self.width-offset-1)
|
||||
if first:
|
||||
if message.nick_color:
|
||||
color = message.nick_color
|
||||
elif message.user:
|
||||
color = message.user.color
|
||||
else:
|
||||
color = None
|
||||
else:
|
||||
color = None
|
||||
if first:
|
||||
if history:
|
||||
time = message.time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
else:
|
||||
time = message.time.strftime("%H:%M:%S")
|
||||
nickname = nick
|
||||
else:
|
||||
time = None
|
||||
nickname = None
|
||||
self.built_lines.append(Line(text=cutted_txt,
|
||||
text_offset=offset,
|
||||
nickname_color=color, time=time,
|
||||
nickname=nickname))
|
||||
nb += 1
|
||||
start_pos = 0
|
||||
end_pos = 0
|
||||
text_len = len(txt)
|
||||
offset = (3 if message.nickname else 1) + len(message.str_time)+len(message.nickname or '')
|
||||
lines = cut_text(txt, self.width-offset-1)
|
||||
for line in lines:
|
||||
self.built_lines.append(Line(msg=message,
|
||||
start_pos=line[0],
|
||||
end_pos=line[1],
|
||||
first=first))
|
||||
first = False
|
||||
start_pos = next_start_pos
|
||||
while len(self.built_lines) > self.lines_nb_limit:
|
||||
self.built_lines.pop(0)
|
||||
return nb
|
||||
return len(lines)
|
||||
|
||||
def refresh(self, room):
|
||||
log.debug('Refresh: %s'%self.__class__.__name__)
|
||||
|
@ -632,15 +596,23 @@ class TextWin(Win):
|
|||
if line is None:
|
||||
self.write_line_separator()
|
||||
else:
|
||||
self.write_time(line.time)
|
||||
self.write_nickname(line.nickname, line.nickname_color)
|
||||
msg = line.msg
|
||||
if line.first:
|
||||
if msg.nick_color:
|
||||
color = msg.nick_color
|
||||
elif msg.user:
|
||||
color = msg.user.color
|
||||
else:
|
||||
color = None
|
||||
self.write_time(msg.str_time)
|
||||
self.write_nickname(msg.nickname, color)
|
||||
if y != self.height-1:
|
||||
self.addstr('\n')
|
||||
self._win.attrset(0)
|
||||
for y, line in enumerate(lines):
|
||||
if not line:
|
||||
continue
|
||||
self.write_text(y, line.text_offset, line.text)
|
||||
self.write_text(y, (3 if line.msg.nickname else 1) + len(line.msg.str_time)+len(line.msg.nickname or ''), line.msg.txt[line.start_pos:line.end_pos])
|
||||
if y != self.height-1:
|
||||
self.addstr('\n')
|
||||
self._win.attrset(0)
|
||||
|
@ -991,10 +963,6 @@ class Input(Win):
|
|||
"""
|
||||
Shell-like completion
|
||||
"""
|
||||
if " " in self.text.strip() or add_after is not None:
|
||||
after = " " # don't put the "," if it's not the begining of the sentence
|
||||
else:
|
||||
after = config.get('after_completion', ',')+" "
|
||||
(y, x) = self._win.getyx()
|
||||
if self.text != '':
|
||||
begin = self.text.split()[-1].lower()
|
||||
|
|
Loading…
Reference in a new issue